The function Reversedll is going into infinite loop here Can anyone help me identify the cause for it????? Program Details : The given function reverseDLL(), which takes head reference as argument and should reverse the elements so that the tail becomes the new head and all pointers are correctly pointed. You need to return the new head of the reversed list.
For a test case : 1 5 1 2 3 4 5 The Output is something like this : 5 4 3 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
def reverseDLL(head): ptr1=head ptr2=ptr1.next temp=head while ptr2: ptr2.prev=ptr2.next ptr2.next=ptr1 ptr1=ptr2 ptr2=ptr2.prev return ptr1 class Node: def __init__(self, data): self.data = data self.next = None self.prev = None class DoublyLinkedList: def __init__(self): self.head = None def push(self, new_data,tail): if not self.head: self.head=Node(new_data) return self.head Nnode=Node(new_data) Nnode.prev=tail tail.next=Nnode return Nnode def printList(self, node): while(node is not None): print (node.data,end=' ') node = node.next if __name__ == '__main__': t=int(input()) for tcs in range(t): n=int(input()) arr=[int(x) for x in input().split()] dll=DoublyLinkedList() tail=None for e in arr: tail=dll.push(e,tail) resHead=reverseDLL(dll.head) dll.printList(resHead) print()
Advertisement
Answer
The problem in reverseDLL
is that it never changes head.next
. As head
will become the last node in the reversed list, it will keep pointing the one-but-last as the next node, which in turn links to that final node again, … leading to the infinite loop.
So you should change this line:
temp=head
With this:
head.next = None
Other Remarks
Although the above will fix your immediate problem, there are some other things to consider:
If you pass an empty list (
head = None
) to that function, it will throw an error. There should be a check for this potentialNone
value.You have a
DoublyLinkedList
class, but then provide the above function as stand alone function. It would make more sense if it were a method of this class. That way, thehead
member of the class instance can be updated when the list is reversed, and remains self-consistent.While you have defined
head
as a member of that class, you have not definedtail
as a member. Instead you require thepush
method to get the currenttail
reference, and it returns the new tail. This is strange. You should really considertail
to be an instance member that is maintained by the class, not by the caller of its methods.printList
is defined as a method of this class, but still you have to provide it the head node as argument. This is strange: the class instance already has ahead
member, so you should not have to provide it as argument.I would not let a method have as a goal to print. Printing should be the responsibility of the caller (separation of concern). Note that none of the standard data structures (like
list
,dict
,…) provide such print methods, and for a good reason. Instead ofprintList
, provide a method that iterates of the list values. That way it becomes very easy for the caller to do what they want with it, like printing.To make printing super easy, provide your class with a
__str__
implementation. This will return the string equivalent of the list. It gets called by default when you doprint(dll)
You can make the constructor of
DoublyLinkedList
more powerful by allowing it to get a list of values to start with.Instead of
push
returning a node, I would actually hide theNode
instances completely from the caller. If you want to return something, then return theDoublyLinkedList
instance itself. That way the caller can chain method calls one after the other, likedll.push(1).push(2)
.
Here is how I would have coded it:
class Node: def __init__(self, data): self.data = data self.next = None self.prev = None class DoublyLinkedList: def __init__(self, values=None): self.head = None self.tail = None # Should be member of the instance # Give possibility to immediate populate with values if values: for data in values: self.push(data) def push(self, new_data): node = Node(new_data) node.prev = self.tail if not self.head: self.head = node else: self.tail.next = node self.tail = node # Keep updated return self # Allow chaining of method calls def __iter__(self): node = self.head # Instance method should use instance while node is not None: yield node.data # Keep it generic: don't print, but yield node = node.next def __str__(self): return "->".join(map(str, self)) def reverse(self): if not self.head: return # Nothing to do prev = self.head curr = prev.next while curr: nxt = curr.next # Establish links between prev and curr curr.next = prev prev.prev = curr # Move on.. prev = curr curr = nxt # Swap head/tail references self.head, self.tail = self.tail, self.head # Set the two None-links that every non-empty list has self.head.prev = None self.tail.next = None
And here is how you can use the above code:
dll = DoublyLinkedList([1,2,3,4,5]) print(dll) # Quite easy to print thanks to __str__ and __iter__ dll.reverse() print(dll)