473,804 Members | 3,953 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Are Python deques linked lists?

I'm looking for a linked list implementation. Something iterable with
constant time insertion anywhere in the list. I was wondering if deque() is
the class to use or if there's something else. Is there?
Thank you...
Dec 9 '07
23 3869
On 2007-12-10, Duncan Booth <du**********@i nvalid.invalidw rote:
Neil Cerutti <ho*****@yahoo. comwrote:
>Python's iterators are unsuitable for mutating the linked list
while iterating--the only major application of linked lists.
Wrapping in a generator won't allow you to use for loop
syntax, unless I'm missing something, which has often
happened.

It is certainly possible to have a linked list implementation
which supports mutation while iterating. Here's a simple
example:

import random

class LinkedElement(o bject):
def __init__(self, value, next):
self.value = value
self.next = next

class LinkedList(obje ct):
def __init__(self, aList):
nxt = None
for el in reversed(aList) :
nxt = LinkedElement(e l, nxt)
self._cursor = self._list = LinkedElement(N one, nxt)
def delete(self, element):
assert self._cursor.ne xt is element
self._cursor.ne xt = self._cursor.ne xt.next

def __iter__(self):
self._cursor = el = self._list
while el.next:
nxt = el.next
yield nxt
if nxt is el.next:
self._cursor = el = nxt

def test():
ll = LinkedList([random.randint( 1,1000) for i in range(10)])

for el in ll:
if el.value%2==0:
ll.delete(el)

print [el.value for el in ll]
if __name__=='__ma in__':
test()

Support for deleting elements other than the current one, and
insertBefore/insertAfter methods is left as an exercise.
Making an object its own iterator for files, but not for a
container. After the deletions, you can never iterate again.

--
Neil Cerutti
Dec 10 '07 #11
Ant
On Dec 9, 10:54 pm, John Machin <sjmac...@lexic on.netwrote:
On Dec 10, 9:43 am, "Just Another Victim of the Ambient Morality"

<ihates...@hotm ail.comwrote:
I'm looking for a linked list implementation. Something iterable with
constant time insertion anywhere in the list.

It's on the shelf between the jar of phlogiston and the perpetual
motion machine.
lol!

--
Ant.
Dec 10 '07 #12
Neil Cerutti wrote:
On 2007-12-10, Duncan Booth <du**********@i nvalid.invalidw rote:
>def test():
ll = LinkedList([random.randint( 1,1000) for i in range(10)])

for el in ll:
if el.value%2==0:
ll.delete(el)

print [el.value for el in ll]
if __name__=='__ma in__':
test()

Support for deleting elements other than the current one, and
insertBefore/insertAfter methods is left as an exercise.

Making an object its own iterator [works] for files, but not for a
container. After the deletions, you can never iterate again.
Look at the test code again -- there is a second iteration after the
deletions (the list comprehension).

However, you will get into trouble if you try to run two simultaneous
iterations over the same LinkedList, so there is room for another
exercise ;)

Peter
Dec 10 '07 #13
Peter Otten <__*******@web. dewrote:
Neil Cerutti wrote:
>On 2007-12-10, Duncan Booth <du**********@i nvalid.invalidw rote:
>>def test():
ll = LinkedList([random.randint( 1,1000) for i in range(10)])

for el in ll:
if el.value%2==0:
ll.delete(el)

print [el.value for el in ll]
if __name__=='__ma in__':
test()

Support for deleting elements other than the current one, and
insertBefor e/insertAfter methods is left as an exercise.

Making an object its own iterator [works] for files, but not for a
container. After the deletions, you can never iterate again.
It isn't its own iterator. The iterator is a separate generator object.
>
Look at the test code again -- there is a second iteration after the
deletions (the list comprehension).

However, you will get into trouble if you try to run two simultaneous
iterations over the same LinkedList, so there is room for another
exercise ;)
Only if you try to modify the list from both of them. Non-modifying
iterations don't interfere. Changing the code to handle modifications from
simultaneous iterations is fairly straightforward but probably tedious to
cover all possible cases: probably the simplest thing is to catch such
cases and throw an exception.

But my point wasn't to give a bullet-proof implementation of a linked list,
just to demonstrate that there is no bar to having one which lets you use a
for loop and delete elements.
Dec 10 '07 #14
On 2007-12-10, Peter Otten <__*******@web. dewrote:
Neil Cerutti wrote:
>>def test():
ll = LinkedList([random.randint( 1,1000) for i in range(10)])

for el in ll:
if el.value%2==0:
ll.delete(el)

print [el.value for el in ll]
if __name__=='__ma in__':
test()

Support for deleting elements other than the current one, and
insertBefor e/insertAfter methods is left as an exercise.

Making an object its own iterator [works] for files, but not
for a container. After the deletions, you can never iterate
again.

Look at the test code again -- there is a second iteration
after the deletions (the list comprehension).
Thanks for the correction. I didn't think that through.
However, you will get into trouble if you try to run two
simultaneous iterations over the same LinkedList, so there is
room for another exercise ;)
I just remembered that iter(an_iterato r) is itself, so nothing
prevents you from saving a reference to it before iterating:

iter = iter(a_linked_l ist)
for it in iter:
if it.value % 2 == 0:
iter.delete()

It looks a little weird, but perhaps it's still better than a
while loop.

--
Neil Cerutti
The pastor will preach his farewell message, after which the choir will sing,
"Break Forth Into Joy." --Church Bulletin Blooper
Dec 10 '07 #15
On 2007-12-10, Neil Cerutti <ho*****@yahoo. comwrote:
On 2007-12-10, Peter Otten <__*******@web. dewrote:
>Neil Cerutti wrote:
>>>def test():
ll = LinkedList([random.randint( 1,1000) for i in range(10)])

for el in ll:
if el.value%2==0:
ll.delete(el)

print [el.value for el in ll]
if __name__=='__ma in__':
test()

Support for deleting elements other than the current one, and
insertBefo re/insertAfter methods is left as an exercise.

Making an object its own iterator [works] for files, but not
for a container. After the deletions, you can never iterate
again.

Look at the test code again -- there is a second iteration
after the deletions (the list comprehension).

Thanks for the correction. I didn't think that through.
>However, you will get into trouble if you try to run two
simultaneous iterations over the same LinkedList, so there is
room for another exercise ;)

I just remembered that iter(an_iterato r) is itself, so nothing
prevents you from saving a reference to it before iterating:

iter = iter(a_linked_l ist)
for it in iter:
if it.value % 2 == 0:
iter.delete()

It looks a little weird, but perhaps it's still better than a
while loop.
Ugh! Assuming you don't shadow built-ins. ;-)

--
Neil Cerutti
Dec 10 '07 #16
I'm looking for a linked list implementation. Something
iterable with constant time insertion anywhere in the list. I
was wondering if deque() is the class to use or if there's
something else. Is there?

The deque is implemented as a list of arrays. See 5.12.1 Recipes
for the trick of using rotate to delete an item from within the
deque. The docs don't spell out the efficiency (in terms of O
notation) of the rotate method, though. You'll have check the
source, or perhaps Raymond is reading and could explain.
Deques have O(1) append/pop behaviors at either. Mid-sequence
insertions, deletions, and rotations are O(n), although the constant
factor is low.

Raymond
Dec 10 '07 #17
Duncan Booth wrote:
Peter Otten <__*******@web. dewrote:
>However, you will get into trouble if you try to run two simultaneous
iterations over the same LinkedList, so there is room for another
exercise ;)
That was a bit vague; I saw the shared _cursor attribute but didn't dig
deeper because I understood that your
point wasn't to give a bullet-proof implementation of a linked
list, just to demonstrate that there is no bar to having one which lets
you use a for loop and delete elements.
>However, you will get into trouble if you try to run two simultaneous
iterations over the same LinkedList
Only if you try to modify the list from both of them.
One deletion is enough to trigger the assertion:
>>from linkedlist import *
items = LinkedList(rang e(10))
a = iter(items)
b = iter(items)
a.next()
<linkedlist.Lin kedElement object at 0xb7d3f12c>
>>x = a.next()
b.next()
<linkedlist.Lin kedElement object at 0xb7d3f12c>
>>items.delete( x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "linkedlist.py" , line 17, in delete
assert self._cursor.ne xt is element
AssertionError
Non-modifying
iterations don't interfere. Changing the code to handle modifications
from simultaneous iterations is fairly straightforward but probably
tedious to cover all possible cases: probably the simplest thing is to
catch such cases and throw an exception.
Or you just rule that delete(x) must occur "immediatel y" after x = next().

Peter
Dec 11 '07 #18
Peter Otten <__*******@web. dewrote:

>Only if you try to modify the list from both of them.

One deletion is enough to trigger the assertion:
Yes, but the assertion isn't intended to be the complete code.
>
Or you just rule that delete(x) must occur "immediatel y" after x =
next().
My original code went something like this:

def delete(self, element):
if self._cursor.ne xt is element:
self._cursor.ne xt = self._cursor.ne xt.next
else:
el = self._list
while el.next:
if el.next is element:
el.next = el.next.next
break
el = el.next

i.e. do the most expected case fast and fall back to the slow method for
other situations. I deleted the 'else' branch because the code I posted
never takes that branch so I have no way to test whether I got it right or
not.

There are lots of ways to handle this. You could save a separate pointer
for each iterator. In fact I would expect that to handle all the possible
variations of inserting and deleting correctly you do need to keep all the
pointers somewhere they can be updated. Or as has been suggested you move
the delete method onto the iterator itself. Actually I suspect that while
it adds some overhead to a loop where you are going to modify the list it
probably results in the cleanest code overall: if you have the iterator you
can safely insert or remove objects without too many worries (just some
basic sanity checking).
Dec 11 '07 #19
On 2007-12-11, Duncan Booth <du**********@i nvalid.invalidw rote:
There are lots of ways to handle this. You could save a
separate pointer for each iterator. In fact I would expect that
to handle all the possible variations of inserting and deleting
correctly you do need to keep all the pointers somewhere they
can be updated. Or as has been suggested you move the delete
method onto the iterator itself. Actually I suspect that while
it adds some overhead to a loop where you are going to modify
the list it probably results in the cleanest code overall: if
you have the iterator you can safely insert or remove objects
without too many worries (just some basic sanity checking).
If you put an instrumented iterator through, say, reversed or
sorted, you'd lose the ability to use it to modify the list--so
it's good for the method to live in the iterator, because you
won't have access to the method anymore, either. In the other
scheme, you could accidentally use an iterator to make
modifications that's ignorant of the necessary bookkeeping (I
suppose you could raise an exception if there's a central
registry of valid iterators, though I like making the method
completely invisible).

I do have one last question about a doubly-linked list. Would you
have to perform any tricks (del statements) to get the garbage
collector to collect every node, or will it just work?

--
Neil Cerutti
Dec 11 '07 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
3673
by: svilen | last post by:
hello again. i'm now into using python instead of another language(s) for describing structures of data, including names, structure, type-checks, conversions, value-validations, metadata etc. And i have things to offer, and to request. And a lot of ideas, but who needs them.... here's an example (from type_struct.py):
34
6436
by: Ville Voipio | last post by:
I would need to make some high-reliability software running on Linux in an embedded system. Performance (or lack of it) is not an issue, reliability is. The piece of software is rather simple, probably a few hundred lines of code in Python. There is a need to interact with network using the socket module, and then probably a need to do something hardware- related which will get its own driver written in C.
5
2289
by: bruce | last post by:
hi... i'm trying to deal with multi-dimension lists/arrays i'd like to define a multi-dimension string list, and then manipulate the list as i need... primarily to add lists/information to the 'list/array' and to compare the existing list information to new lists i'm not sure if i need to import modules, or if the base python install i have is sufficient. an example, or pointer to examples would be good...
11
3789
by: efrat | last post by:
Hello, I'm planning to use Python in order to teach a DSA (data structures and algorithms) course in an academic institute. If you could help out with the following questions, I'd sure appreciate it: 1. What exactly is a Python list? If one writes a, then is the complexity Theta(n)? If this is O(1), then why was the name "list" chosen? If this is indeed Theta(n), then what alternative should be used? (array does not seem suited for...
0
219
by: Kurt B. Kaiser | last post by:
Patch / Bug Summary ___________________ Patches : 421 open ( +3) / 3530 closed ( +8) / 3951 total (+11) Bugs : 963 open ( +4) / 6426 closed (+21) / 7389 total (+25) RFE : 255 open ( +5) / 246 closed ( +1) / 501 total ( +6) New / Reopened Patches ______________________
19
7829
by: Dongsheng Ruan | last post by:
with a cell class like this: #!/usr/bin/python import sys class Cell: def __init__( self, data, next=None ): self.data = data
15
64542
by: Alex Snast | last post by:
Hello I'm new to python and i can't figure out how to write a reverse for loop in python e.g. the python equivalent to the c++ loop for (i = 10; i >= 0; --i)
0
9706
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9582
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10580
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10335
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10082
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9157
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5525
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5652
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3821
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.