6

I am constructing a doubly linked list and I am struggling on construct a doubly linked list iterator method in PYTHON.

This is my code so far

class DoubleListNode:
 def __init__(self,data):
 self.data=data
 self.prev = None
 self.next= None
class ListIterator:
 def __init__(self):
 self._current = self.head
 def __iter__(self):
 return self
 def next(self):
 if self.size == 0 :
 raise StopIteration
 else:
 item = self._current.data
 self._current=self._current.next
 return item
class DoublyLinkedList:
 def __init__(self):
 self.head= None
 self.tail= None
 self.size = 0
 def add(self,data):
 newnode= DoubleListNode(data)
 self.size+=1
 if self.head is None:
 self.head = newnode
 self.tail = self.head
 elif data < self.head.data: # before head
 newnode.next = self.head
 self.head.prev= newnode
 self.head= newnode
 elif data > self.tail.data: # at the end
 newnode.prev= self.tail
 self.tail.next= newnode
 self.tail=newnode
 else:
 curNode = self.head
 while curNode is not None and curNode.data < data:
 curNode=curNode.next 
 newnode.next= curNode
 newnode.prev=curNode.prev
 curNode.prev.next= newnode
 curNode.prev=newnode
 def remove(self,data):
 curNode=self.head
 while curNode is not None and curNode.data!= data:
 curNode= curNode.next
 if curNode is not None:
 self.size -= 1
 if curNode is self.head:
 self.head= curNode.next
 else:
 curNode.prev.next=curNode.next
 if curNode is self.tail:
 self.tail=curNode.prev
 else:
 curNode.next.prev=curNode.prev

When I run a test it said TypeError: iteration over non-sequence. Did I do something wrong ?

Blckknght
105k11 gold badges135 silver badges188 bronze badges
asked Mar 29, 2013 at 20:25
4
  • In __init__ where is self.head coming from? And how do you iterate? Commented Mar 29, 2013 at 20:29
  • How are you creating your ListIterator object? Something is definitely wrong there, since self._current = self.head will raise and AttributeError in __init__(). Commented Mar 29, 2013 at 20:31
  • I implemented a doubly linked list earlier here is the code for doubly linked list class class DoublyLinkedList: #init def __init__(self): self.head= None self.tail= None self.size = 0 in that class I have add remove len methods Commented Mar 29, 2013 at 20:36
  • Please help others to help you by posting the more completed code, starting with init Commented Mar 29, 2013 at 21:06

5 Answers 5

5

As posted, the code doesn't initialize (i.e. self.head isn't defined).

But overall, you are on the right track. Take a look at the source for Python's collections.OrderedDict for a worked-out example of traversing a doubly linked list.

Here's a simplified example:

class Link:
 def __init__(self, value, prev=None, next=None):
 self.value = value
 self.prev = prev
 self.next = next
 def __iter__(self):
 here = self
 while here:
 yield here.value
 here = here.next
 def __reversed__(self):
 here = self
 while here:
 yield here.value
 here = here.prev
if __name__ == '__main__':
 a = Link('raymond')
 b = Link('rachel', prev=a); a.next=b
 c = Link('matthew', prev=b); b.next=c
 print 'Forwards:'
 for name in a:
 print name
 print
 print 'Backwards:'
 for name in reversed(c):
 print name
answered Mar 29, 2013 at 20:30

1 Comment

The message TypeError: iteration over non-sequence means that Python cannot find an __iter__ method for an object. Also note that in Python 3, we use __next__ instead of next.
2

I think there are two important things to fix.

First, your DoublyLinkedList class doesn't have an __iter__ method. You probably want to create one that returns a ListIterator instance. Perhaps you're trying to do this manually, but this would be the normal approach.

Second, you need to fix the code in your ListIterator to work properly. Currently your __init__ method doesn't initialize things correctly, and your next method tries to access member variables like size that don't exist.

Here's an implementation that I think will work:

def ListIterator(object):
 def __init__(self, node):
 self.current = node
 def __iter__(self):
 return self
 def next(self):
 if self.current is None:
 raise StopIteration()
 result = self.current.data
 self.current = self.current.next
 return result
class DoublyLinkedList(object):
 # all your current stuff, plus:
 def __iter__(self):
 return ListIterator(self.head)

As a side note, in your current code you're defining classes with no bases. This is fine in Python 3 (where object will be the base by default), but in Python 2 this will result in getting an "old-style" class. Old-style classes are deprecated, and you'll find that some language features won't work properly with them (though not any of the features involved in iteration, as far as I know). On the other hand, if you are already using Python 3 then you need to define a __next__ method in the iterator class, rather than next (without the underscores).

answered Mar 31, 2013 at 2:57

Comments

1

Here is an example for Doubly Linked List class.

class Node:
 def __init__(self, val):
 self.data = val
 self.next = None
 self.prev = None
class LinkedList:
 def __init__(self):
 self.head = None
 self.tail = None
 self.count = 0
 def insert(self, val):
 newNode = Node(val)
 if self.count == 0:
 self.head = newNode
 self.tail = newNode
 else:
 self.head.prev = newNode
 newNode.next = self.head
 self.head = newNode
 self.count += 1
 def insertToEnd(self, val):
 newNode = Node(val)
 if self.count == 0:
 self.head = newNode
 self.tail = newNode
 else:
 self.tail.next = newNode
 newNode.prev = self.tail
 self.tail = newNode
 self.count += 1
 def search(self, val):
 p = self.head
 while p is not None:
 if p.data == val:
 return p
 p = p.next
 def delete(self, val):
 curNode = self.head
 while curNode != None:
 if curNode.data == val:
 if curNode.prev != None:
 curNode.prev.next = curNode.next
 else:
 self.head = curNode.next
 if curNode.next != None:
 curNode.next.prev = curNode.prev
 else:
 self.tail = curNode.prev
 self.count -= 1
 curNode = curNode.next
 def show(self):
 s = ""
 p = self.head
 while p is not None:
 s += str(p.data) + ' ';
 p = p.next
 print(s + "| count: " + str(self.count))
answered Jul 12, 2016 at 7:13

Comments

0

Based on what you post, may I suggest:

class ListIterator:
 # other stuff ...
 def __iter__(self):
 while self._current:
 yield self._current.data
 self._current = self._current.next
 self._current = self.head # Reset the current pointer

You don't have to implement next()

Update

Here is an example usage:

for data in myListIterator:
 print data
# Without reset, the second time around won't work:
for data in myListIterator:
 print data
answered Mar 29, 2013 at 21:15

Comments

0

If you're just iterating/traversing through the linked list you can try a basic set up for both the node and the Doublyll objects, and replace the val with whatever you defined in your code:

class Node:
 def __init__(self, val):
 self.val = val
 self.next = None
 self.prev = None
class Doublyll:
 def __init__(self):
 self.head = None
 self.tail = None
 self.size = 0
 def traversal(self):
 curr = self.head
 while curr:
 print(curr.val, end='--')
 curr = curr.next 
 print('None')
Yannis
1,7198 gold badges30 silver badges51 bronze badges
answered Aug 29, 2024 at 20:52

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.