Related
I am now working on reversing a linked list in groups, but encountering some issues.
The question is:
Given a LinkedList with ‘n’ nodes, reverse it based on its size in the following way:
If ‘n’ is even, reverse the list in a group of n/2 nodes. If n is odd,
keep the middle node as it is, reverse the first ‘n/2’ nodes and
reverse the last ‘n/2’ nodes.
My approach is:
def lenLinkedlist(head):
count = 0
current = head
while current:
current = current.next
count += 1
return count
def reverseInGroupPart(head, n):
count = 0
previous, current, next = None, head, None
while current and count < n//2:
next = current.next
current.next = previous
previous = current
current = next
count += 1
# even
if n%2 == 0:
# current at middle right now
# head supports to be middle now
head.next = reverseInGroupPart(current, n)
# odd
else:
# current at middle now
head.next = current
current.next = reverseInGroupPart(current.next, n)
return previous
def reverseGroups(head):
n = lenLinkedlist(head)
if n%2 == 0:
return reverseInGroupPart(head, n)
else:
return reverseInGroupPart(head, n)
class Node:
def __init__(self, _value, _next = None):
self.value = _value
self.next = _next
def print_list(self):
temp = self
while temp:
print(temp.value, end = ' ')
temp = temp.next
print()
def main():
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
head.next.next.next.next.next = Node(6)
print('original linked list is: ', end = '')
head.print_list()
result = reverseGroups(head)
print('reverse of linked list is ', end = '')
result.print_list()
main()
With errors:
Traceback (most recent call last):
File "/Users/PycharmProjects/tester/main.py", line 62, in <module>
main()
File "/Users/PycharmProjects/tester/main.py", line 58, in main
result = reverseGroups(head)
File "/Users/PycharmProjects/tester/main.py", line 33, in reverseGroups
return reverseInGroupPart(head, n)
File "/Users/PycharmProjects/tester/main.py", line 22, in reverseInGroupPart
head.next = reverseInGroupPart(current, n)
File "/Users/PycharmProjects/tester/main.py", line 22, in reverseInGroupPart
head.next = reverseInGroupPart(current, n)
File "/Users/PycharmProjects/tester/main.py", line 22, in reverseInGroupPart
head.next = reverseInGroupPart(current, n)
[Previous line repeated 993 more times]
File "/Users/PycharmProjects/tester/main.py", line 19, in reverseInGroupPart
if n%2 == 0:
RecursionError: maximum recursion depth exceeded in comparison
original linked list is: 1 2 3 4 5 6
Process finished with exit code 1
I tried to use the recursion method to solve the question, but not sure what caused the error. Thanks.
Your reverseGroups() function doesn't make much sense as it has an if that does the same thing in both branches.
I'm going to take a different approach. First, I'm going to change your functions to instead be methods of Node. Next, I'm going to make most of those methods recursive, just for practice. Finally, I'm going to make the reversing of segments of the linked list recursive, but not the higher level logic of rearranging portions of the linked list as that doesn't seem like a recursive problem:
class Node:
def __init__(self, value, _next=None):
self.value = value
self.next = _next
def printLinkedlist(self):
print(self.value, end=' ')
if self.next:
self.next.printLinkedlist()
else:
print()
def lengthLinkedlist(self):
count = 1
if self.next:
count += self.next.lengthLinkedlist()
return count
def reverseLinkedList(self, length):
head, rest = self, self.next
if length > 1:
if rest:
head, rest = rest.reverseLinkedList(length - 1)
self.next.next = self
self.next = None
return head, rest
def reverseGroups(self):
head = self
length = self.lengthLinkedlist()
if length > 3:
tail = self
head, rest = self.reverseLinkedList(length//2) # left
if length % 2 == 1: # odd, skip over middle
tail.next = rest
tail = tail.next
rest = tail.next
tail.next, _ = rest.reverseLinkedList(length//2) # right
return head
if __name__ == '__main__':
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
head.next.next.next.next.next = Node(6)
head.next.next.next.next.next.next = Node(7)
print('original linked list is: ', end='')
head.printLinkedlist()
head = head.reverseGroups()
print('reverse of linked list is ', end='')
head.printLinkedlist()
OUTPUT
> python3 test.py
original linked list is: 1 2 3 4 5 6 7
reverse of linked list is 3 2 1 4 7 6 5
>
And if we comment out the last link:
# head.next.next.next.next.next.next = Node(7)
Then our output is:
> python3 test.py
original linked list is: 1 2 3 4 5 6
reverse of linked list is 3 2 1 6 5 4
>
For me, this problem turned out to be one of careful bookkeepping. I also had to first implement reverseLinkedList() iteratively, get reverseGroups() working, and then go back and reimplement reverseLinkedList() recursively.
I'd approach this problem in small steps. For starters, the class structure could use a bit of an overhaul to make it easier to work with. I'd create a LinkedList class and take advantage of the dunder methods like __repr__, __len__ and __iter__ to make the code cleaner and more Pythonic. Use snake_case instead of camelCase per PEP-8.
from functools import reduce
class Node:
def __init__(self, value, next_=None):
self.value = value
self.next = next_
def __repr__(self):
return str(self.value)
class LinkedList:
def __init__(self, els):
self.head = None
for e in reversed(els):
self.head = Node(e, self.head)
def __iter__(self):
curr = self.head
while curr:
yield curr
curr = curr.next
def __getitem__(self, i):
try:
return list(zip(self, range(i + 1)))[-1][0]
except IndexError:
raise IndexError(i)
def __len__(self): # possibly better to cache instead of compute on the fly
return reduce(lambda a, _: a + 1, self, 0)
def __repr__(self):
return "[" + "->".join([str(x) for x in self]) + "]"
if __name__ == "__main__":
for length in range(8):
ll = LinkedList(list(range(length)))
print("original:", ll)
Before diving into the algorithm, I should note that linked lists are a poor fit for recursion (unless the language is tail-call optimized) because each recursive step only reduces the problem space by 1 node. This incurs a lot of call overhead, risks blowing the stack if the list has more than a measly ~1000 elements and generally doesn't offer much elegance/readability payoff to offset these downsides.
On the other hand, trees are a better fit for recursion because the call stack pops frequently during a traversal of a well-balanced tree, keeping the depth to a logarithmic rather than a linear scale. The same is true for sorting lists with quicksort or mergesort or performing binary searches.
Linked list algorithms also tend to require many references to previous and next nodes, along with bookkeeping nodes for dummy heads and tails, state that isn't easy to access in a discrete stack frame. Iteratively, you can access all of the state you need directly from the loop block without parameters.
That said, here's a simple iterative reversal routine I'll use as the basis for writing the rest of the code:
class LinkedList:
# ...
def reverse(self):
prev = None
curr = self.head
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
self.head = prev
This needs to be made more general: if I can refactor this algorithm to reverse a subset of the list between a node and a sublist length, the problem is pretty much solved because we can apply this algorithm to the first and second halves of the list separately.
The first step towards that is to avoid hardcoding self.head and pass it in as a parameter, returning the new head for the reversed sublist. This is still in-place (I assume that to be a requirement):
class LinkedList:
# ...
def _reverse_from(self, curr):
prev = None
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
def reverse(self):
self.head = self.reverse_from(self.head)
Next, we can add an index counter to enable reversal of a subset of the linked list starting from a node.
To make this work, the new tail node (old front node of the sublist) needs to be linked to the back of the list left after the reversed subsection or we'll wind up with the old head/new tail node pointing to None and chopping off the tail.
class LinkedList:
# ...
def _reverse_from(self, start, length=-1):
curr = start
prev = None
while curr and length != 0:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
length -= 1
if start:
# link the new tail (old head) with the back of the list
start.next = curr
return prev
Finally, add the client-facing function to reverse each half separately:
class LinkedList:
# ...
def reverse_halves(self):
length = len(self)
if length < 4:
return
mid_idx = length // 2
self.head = self._reverse_from(self.head, mid_idx)
if length % 2 == 0:
mid_idx -= 1
mid = self[mid_idx]
mid.next = self._reverse_from(mid.next)
Putting it all together with sample runs, we get:
from functools import reduce
class Node:
def __init__(self, value, next_=None):
self.value = value
self.next = next_
def __repr__(self):
return str(self.value)
class LinkedList:
def __init__(self, els):
self.head = None
for e in reversed(els):
self.head = Node(e, self.head)
def _reverse_from(self, start, length=-1):
curr = start
prev = None
while curr and length != 0:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
length -= 1
if start:
start.next = curr
return prev
def reverse(self):
self.head = self._reverse_from(self.head)
def reverse_halves(self):
length = len(self)
if length < 4:
return
mid_idx = length // 2
self.head = self._reverse_from(self.head, mid_idx)
if length % 2 == 0:
mid_idx -= 1
mid = self[mid_idx]
mid.next = self._reverse_from(mid.next)
def __iter__(self):
curr = self.head
while curr:
yield curr
curr = curr.next
def __getitem__(self, i):
try:
return list(zip(self, range(i + 1)))[-1][0]
except IndexError:
raise IndexError(i)
def __len__(self):
return reduce(lambda a, _: a + 1, self, 0)
def __repr__(self):
return "[" + "->".join([str(x) for x in self]) + "]"
if __name__ == "__main__":
for length in range(8):
ll = LinkedList(list(range(length)))
print("original:", ll)
ll.reverse_halves()
print("reversed:", ll, "\n")
Output:
original: []
reversed: []
original: [0]
reversed: [0]
original: [0->1]
reversed: [0->1]
original: [0->1->2]
reversed: [0->1->2]
original: [0->1->2->3]
reversed: [1->0->3->2]
original: [0->1->2->3->4]
reversed: [1->0->2->4->3]
original: [0->1->2->3->4->5]
reversed: [2->1->0->5->4->3]
original: [0->1->2->3->4->5->6]
reversed: [2->1->0->3->6->5->4]
Please understanding my English.
I have some question about the liked list
class Node:
''' Node for a linked list '''
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __str__(self):
''' Given a node, print the node and the following list'''
if self == None:
return ""
return str(self.data) + " " + (self.next.__str__() if self.next else "")
def __repr__(self):
return self.__str__()
def head(lst):
''' Remove the first element from a linked List,
and return a tuple with the removed and the rest of the list'''
if lst == None:
print("Invalid Input")
return
rest = lst.next
lst.next = None
return(lst, rest)
# Test : Creating nodes and connecting them as a linked list
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node1.next = node2
node2.next = node3
print(node1) # 1 2 3
print(node1.next.next.data) # 3
lst1 = Node('a', (Node('b', (Node('c', (Node('d')))))))
print(lst1) # a b c d
print(lst1.next.next.next.data) # d
(x,xs) = head(lst1)
print(x.data) # a
print(xs) # b c d
(z,zs) = head(node3)
print(z.data) # 3
print(zs) # None
lnklst = Node (2, Node(1, Node(4, Node(3))))
## Sorting
I understand untill this line but I can't understand 'def max'
def max(lst):
'''Given a list, find mx node(the node with largest number),
remove it from the list, and return a tuple with
the removed node and the modified list.
if lst is an empty, return (None, None)
if lst is a singleton, return (lst, None)'''
if lst == None:
return (None, None)
if lst.next == None: # lst has one node
return (lst, None)
original = lst # lst will be used to traverse the node
# Finding the mx, we need to find the previous node as well
# to delete it from the list.
prev = lst
mx = lst
while lst.next:
if lst.next.data > mx.data:
mx = lst.next
prev = lst
lst = lst.next
# Three Cases : mx is the first, the last, or in the middle
if prev == mx: # mx is the first
pass
mx.next = None
elif mx.next == None: # mx is the last
pass
else: # mx is in the middle
pass
return(mx,rest)
def addList(lst, node):
''' add the node to the front of lst'''
if lst == None:
return node
node.next = lst
return node
def sortList(lst):
''' sort a linked list in an ascending order '''
if lst == None:
return None
(x, xs) = max(lst)
sort = x
while xs:
(x,xs) = max(xs)
sort = addList(sort,x)
return sort
# Construction of list with input data and Test
lst = Node(5,(Node(1,(Node(6,(Node(7,(Node(10,(Node(2,(Node(1,(Node(9)))))))))))))))
lst1 = Node(5,(Node(1,Node(2,(Node(3))))))
lst2 = Node(2,(Node(1)))
lst3 = Node(1,(Node(2,(Node(3,(Node(4,(Node(5,(Node(6,(Node(7,(Node(8)))))))))))))))
lst4 = Node(8,(Node(7,(Node(5,(Node(4,(Node(3,(Node(2,(Node(1,(Node(0)))))))))))))))
lst5 = Node(2,(Node(2,Node(2,(Node(2))))))
print ("Input : " + lst.__str__())
print(sortList(lst))
And What code do I input at pass line in 'def max'?
Can you teach me how to work 'def shortlist'
Can you teach me what code do I input at pass line in 'def max'
and if you have the better idea this code please tell me.
Any help is greatly appreciated.
max() separates the node with the max data from the input list and return a tuple (max, list_without_max).
sortlist does the following
calls max() to find the max node and remove it from the input list.
add this max node to a new list sort.
Loop until the input list is empty
in max,
if prev == mx: # mx is the first
rest = mx.next # rest point to the next of mx
mx.next = None
elif mx.next == None: # mx is the last
prev.next = None
rest = original
else: # mx is in the middle
prev.next = mx.next
rest = original
mx.next = None
I'm not 100% sure it's correct. Hope it helps.
here is my code:
def merge_lists(head1, head2):
if head1 is None and head2 is None:
return None
if head1 is None:
return head2
if head2 is None:
return head1
if head1.value < head2.value:
temp = head1
else:
temp = head2
while head1 != None and head2 != None:
if head1.value < head2.value:
temp.next = head1
head1 = head1.next
else:
temp.next = head2
head2 = head2.next
if head1 is None:
temp.next = head2
else:
temp.next = head1
return temp
pass
the problem here is stucked in the infinite loop.can any one tell me what the problem is
the examples are:
assert [] == merge_lists([],[])
assert [1,2,3] == merge_lists([1,2,3], [])
assert [1,2,3] == merge_lists([], [1,2,3])
assert [1,1,2,2,3,3,4,5] == merge_lists([1,2,3], [1,2,3,4,5])
The problem with the current code is that it causes a side-effect of the temp node's next before it navigates to the next node from the current node. This is problematic when the current temp node is the current node.
That is, imagine this case:
temp = N
temp.next = N # which means N.next = N
N = N.next # but from above N = (N.next = N) -> N = N
There is a corrected version, with some other updates:
def merge_lists(head1, head2):
if head1 is None:
return head2
if head2 is None:
return head1
# create dummy node to avoid additional checks in loop
s = t = node()
while not (head1 is None or head2 is None):
if head1.value < head2.value:
# remember current low-node
c = head1
# follow ->next
head1 = head1.next
else:
# remember current low-node
c = head2
# follow ->next
head2 = head2.next
# only mutate the node AFTER we have followed ->next
t.next = c
# and make sure we also advance the temp
t = t.next
t.next = head1 or head2
# return tail of dummy node
return s.next
Recursive algorithm for merging two sorted linked lists
def merge_lists(h1, h2):
if h1 is None:
return h2
if h2 is None:
return h1
if (h1.value < h2.value):
h1.next = merge_lists(h1.next, h2)
return h1
else:
h2.next = merge_lists(h2.next, h1)
return h2
Complete code:-
Definition of "Node" class for every single node of Linked List.
class Node:
def __init__(self,data):
self.data = data
self.next = None
Definition of "linkedlist" Class.
class linkedlist:
def __init__(self):
self.head = None
Definition of "Merge" function.
The parameters "ll1" and "ll2" are the head of the two linked list.
def merge_lists(ll1, ll2):
if ll1 is None:
return ll2
if ll2 is None:
return ll1
if (ll1.data < ll2.data):
ll1.next = merge_lists(ll1.next, ll2)
return ll1
else:
ll2.next = merge_lists(ll2.next, ll1)
return ll2
Taking input into list.
l1 = []
try:
l1 = list(map(int,input().strip().split()))
except EOFError:
pass
l2 = []
try:
l2 = list(map(int,input().strip().split()))
except EOFError:
pass
Creating linked list namely ll1 and ll2 from the input list values.
ll1 = linkedlist()
ll1.head = Node(l1[0])
itr1 = ll1.head
for i in range(1,n1):
temp = Node(l1[i])
itr1.next = temp
itr1 = itr1.next
ll2 = linkedlist()
ll2.head = Node(l2[0])
itr2 = ll2.head
for i in range(1,n2):
temp = Node(l2[i])
itr2.next = temp
itr2 = itr2.next
Merging two sorted linked list using merge function by passing the head of the two linked list
itr = merge(ll1.head,ll2.head)
"merge" function returns an iterator itself whose values are printed as:
while itr != None:
print(itr.data,end=" ")
itr = itr.next
Custom input and output:-
Input
1
4
1 3 5 7
4
2 4 6 12
Output
1 2 3 4 5 6 7 12
To me, it was more pythonic to convert a LinkedList to list and back.
I also implemented print function to output the LinkedList, which helps for testing and debugging.
def ln_to_list(ln):
tmp = ln
lst = [ln.val]
while tmp.next:
tmp = tmp.next
lst.append(tmp.val)
return lst
def print_ln(ln):
return '->'.join([str(el) for el in ln_to_list(ln)])
def ln_from_list(lst):
if not lst or len(lst) == 0:
return None
head = ListNode(lst[0])
tmp = head
for i in lst[1:]:
tmp.next = ListNode(i)
tmp = tmp.next
return head
First of all let me make clear, it is the problem of the leet code as I mentioned so here I was just trying to answer the problem, the logic itself.
Time complexity: O(n+m) where n is len(l1) and m is len(l2) as we are traversing only once.
Space complexity: O(1), we don't create any new object and just reconnect each other.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def mergeTwoLists(self, l1, l2):
head = res = ListNode()
while l1 and l2:
if l1.val <= l2.val:
res.next = l1
l1 = l1.next
else:
res.next = l2
l2 = l2.next
res = res.next
if l1: res.next = l1
if l2: res.next = l2
return(head.next)
#create a new linkedlist which is used to store the result
#here I have used two refereces to the same list since I should return the root of the list
#head will be used during the process and res will be returned. –
here this is the node definition
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
this is the conversion for the code a number to linked list
def number_to_list(number):
head,tail = None,None
p = True
for x in str(number):
if x=='-':
p = False
continue
else:
if p:
node = Node(int(x))
else:
node = Node(int("-"+x))
if head:
tail.next = node
else:
head = node
tail = node
return head
pass
this is code for conversion of linked list to number
def list_to_number(head):
neg = False
num = ''
for number in head:
val = str(number)
if (val.find('-')!= -1):
neg = True
num=num+val.replace('-','')
if (neg==False):
return int(num)
else:
return -1*int(num)
pass
here it is the test cases
def test_number_to_list():
import listutils
head = number_to_list(120)
assert [1,2,0] == listutils.from_linked_list(head)
assert 120 == list_to_number(head)
head = number_to_list(0)
assert [0] == listutils.from_linked_list(head)
assert 0 == list_to_number(head)
head = number_to_list(-120)
assert [-1, -2, 0] == listutils.from_linked_list(head)
assert -120 == list_to_number(head)
here from_linked_list means
# avoids infinite loops
def from_linked_list(head):
result = []
counter = 0
while head and counter < 100: # tests don't use more than 100 nodes, so bail if you loop 100 times.
result.append(head.value)
head = head.next
counter += 1
return result
at last in this the problem is while converting the linked list to single number it is encountering an error i.e.,node object is not iterable
please help me out of this to write the code
def list_to_number(head):
neg = False
num = ''
for number in head:
val = str(number)
TypeError: 'Node' object is not iterable
here this is the traceback
The
for number in head:
is not a correct way to iterate of the list.
You need to start from head and then follow the chain of next references.
Note that if __iter__ is defined on Node like this:
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
def __iter__(self):
that = self
while that is not None:
yield that.value
that = that.next
Then:
for number in head:
Would actually work.
I am asked to reverse a which takes head as parameter where as head is a linked list e.g.: 1 -> 2 -> 3 which was returned from a function already defined I tried to implement the function reverse_linked_list in this way:
def reverse_linked_list(head):
temp = head
head = None
temp1 = temp.next
temp2 = temp1.next
temp1.next = None
temp2.next = temp1
temp1.next = temp
return temp2
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
def to_linked_list(plist):
head = None
prev = None
for element in plist:
node = Node(element)
if not head:
head = node
else:
prev.next = node
prev = node
return head
def from_linked_list(head):
result = []
counter = 0
while head and counter < 100: # tests don't use more than 100 nodes, so bail if you loop 100 times.
result.append(head.value)
head = head.next
counter += 1
return result
def check_reversal(input):
head = to_linked_list(input)
result = reverse_linked_list(head)
assert list(reversed(input)) == from_linked_list(result)
It is called in this way: check_reversal([1,2,3]). The function I have written for reversing the list is giving [3,2,1,2,1,2,1,2,1] and works only for a list of length 3. How can I generalize it for a list of length n?
The accepted answer doesn't make any sense to me, since it refers to a bunch of stuff that doesn't seem to exist (number, node, len as a number rather than a function). Since the homework assignment this was for is probably long past, I'll post what I think is the most effective code.
This is for doing a destructive reversal, where you modify the existing list nodes:
def reverse_list(head):
new_head = None
while head:
head.next, head, new_head = new_head, head.next, head # look Ma, no temp vars!
return new_head
A less fancy implementation of the function would use one temporary variable and several assignment statements, which may be a bit easier to understand:
def reverse_list(head):
new_head = None # this is where we build the reversed list (reusing the existing nodes)
while head:
temp = head # temp is a reference to a node we're moving from one list to the other
head = temp.next # the first two assignments pop the node off the front of the list
temp.next = new_head # the next two make it the new head of the reversed list
new_head = temp
return new_head
An alternative design would be to create an entirely new list without changing the old one. This would be more appropriate if you want to treat the list nodes as immutable objects:
class Node(object):
def __init__(self, value, next=None): # if we're considering Nodes to be immutable
self.value = value # we need to set all their attributes up
self.next = next # front, since we can't change them later
def reverse_list_nondestructive(head):
new_head = None
while head:
new_head = Node(head.value, new_head)
head = head.next
return new_head
I found blckknght's answer useful and it's certainly correct, but I struggled to understand what was actually happening, due mainly to Python's syntax allowing two variables to be swapped on one line. I also found the variable names a little confusing.
In this example I use previous, current, tmp.
def reverse(head):
current = head
previous = None
while current:
tmp = current.next
current.next = previous # None, first time round.
previous = current # Used in the next iteration.
current = tmp # Move to next node.
head = previous
Taking a singly linked list with 3 nodes (head = n1, tail = n3) as an example.
n1 -> n2 -> n3
Before entering the while loop for the first time, previous is initialized to None because there is no node before the head (n1).
I found it useful to imagine the variables previous, current, tmp 'moving along' the linked list, always in that order.
First iteration
previous = None
[n1] -> [n2] -> [n3]
current tmp
current.next = previous
Second iteration
[n1] -> [n2] -> [n3]
previous current tmp
current.next = previous
Third iteration
# next is None
[n1] -> [n2] -> [n3]
previous current
current.next = previous
Since the while loop exits when current == None the new head of the list must be set to previous which is the last node we visited.
Edited
Adding a full working example in Python (with comments and useful str representations). I'm using tmp rather than next because next is a keyword. However I happen to think it's a better name and makes the algorithm clearer.
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return str(self.value)
def set_next(self, value):
self.next = Node(value)
return self.next
class LinkedList:
def __init__(self, head=None):
self.head = head
def __str__(self):
values = []
current = self.head
while current:
values.append(str(current))
current = current.next
return ' -> '.join(values)
def reverse(self):
previous = None
current = self.head
while current.next:
# Remember `next`, we'll need it later.
tmp = current.next
# Reverse the direction of two items.
current.next = previous
# Move along the list.
previous = current
current = tmp
# The loop exited ahead of the last item because it has no
# `next` node. Fix that here.
current.next = previous
# Don't forget to update the `LinkedList`.
self.head = current
if __name__ == "__main__":
head = Node('a')
head.set_next('b').set_next('c').set_next('d').set_next('e')
ll = LinkedList(head)
print(ll)
ll.revevse()
print(ll)
Results
a -> b -> c -> d -> e
e -> d -> c -> b -> a
Here is a way to reverse the list 'in place'. This runs in constant time O(n) and uses zero additional space.
def reverse(head):
if not head:
return head
h = head
q = None
p = h.next
while (p):
h.next = q
q = h
h = p
p = h.next
h.next = q
return h
Here's an animation to show the algorithm running.
(# symbolizes Null/None for purposes of animation)
Node class part borrowed from interactive python.org: http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html
I created the reversed function.
All comments in the loop of reverse meant for 1st time looping. Then it continues.
class Node():
def __init__(self,initdata):
self.d = initdata
self.next = None
def setData(self,newdata):
self.d = newdata
def setNext(self,newnext):
self.next = newnext
def getData(self):
return self.d
def getNext(self):
return self.next
class LinkList():
def __init__(self):
self.head = None
def reverse(self):
current = self.head >>> set current to head(start of node)
previous = None >>> no node at previous
while current !=None: >>> While current node is not null, loop
nextt = current.getNext() >>> create a pointing var to next node(will use later)
current.setNext(previous) >>> current node(or head node for first time loop) is set to previous(ie NULL), now we are breaking the link of the first node to second node, this is where nextt helps(coz we have pointer to next node for looping)
previous = current >>> just move previous(which was pointing to NULL to current node)
current = nextt >>> just move current(which was pointing to head to next node)
self.head = previous >>> after looping is done, (move the head to not current coz current has moved to next), move the head to previous which is the last node.
You can do the following to reverse a singly linked list (I assume your list is singly connected with each other).
First you make a class Node, and initiate a default constructor that will take the value of data in it.
class Node:
def __init__(self, data):
self.data = data
self.next = None
This solution will reverse your linked list "iteratively".
I am making a class called SinglyLinkedList which will have a constructor:
class SinglyLinkedList:
def __init__(self):
self.head = None
then I have written a method to reverse the list, print the length of the list, and to print the list itself:
# method to REVERSE THE LINKED LIST
def reverse_list_iterative(self):
prev = None
current = self.head
following = current.next
while (current):
current.next = prev
prev = current
current = following
if following:
following = following.next
self.head = prev
# Method to return the length of the list
def listLength(self):
count = 0
temp = self.head
while (temp != None):
temp = temp.next
count += 1
return count
# Method to print the list
def printList(self):
if self.head == None:
print("The list is empty")
else:
current_node = self.head
while current_node:
print(current_node.data, end = " -> ")
current_node = current_node.next
if current_node == None:
print("End")`
After that I hard code the list, and its contents and then I link them
if __name__ == '__main__':
sll = SinglyLinkedList()
sll.head = Node(1)
second = Node(2)
third = Node(3)
fourth = Node(4)
fifth = Node(5)
# Now linking the SLL
sll.head.next = second
second.next = third
third.next = fourth
fourth.next = fifth
print("Length of the Singly Linked List is: ", sll.listLength())
print()
print("Linked List before reversal")
sll.printList()
print()
print()
sll.reverse_list_iterative()
print("Linked List after reversal")
sll.printList()
Output will be:
Length of the Singly Linked List is: 5
Linked List before reversal 1 -> 2 -> 3 -> 4 -> 5 -> End
Linked List after reversal
5 -> 4 -> 3 -> 2 -> 1 -> End
I tried a different approach, in place reversal of the LList.
Given a list 1,2,3,4
If you successively swap nearby nodes,you'll get the solution.
len=3 (size-1)
2,1,3,4
2,3,1,4
2,3,4,1
len=2 (size-2)
3,2,4,1
3,4,2,1
len=1 (size-3)
4,3,2,1
The code below does just that. Outer for loop successively reduces the len of list to swap between. While loop swaps the data elements of the Nodes.
def Reverse(head):
temp = head
llSize = 0
while temp is not None:
llSize += 1
temp = temp.next
for i in xrange(llSize-1,0,-1):
xcount = 0
temp = head
while (xcount != i):
temp.data, temp.next.data = temp.next.data, temp.data
temp = temp.next
xcount += 1
return head
This might not be as efficient as other solutions, but helps to see the problem in a different light. Hope you find this useful.
Here is the whole thing in one sheet. Contains the creation of a linked list, and code to reverse it.
Includes an example so you can just copy and paste into an idle .py file and run it.
class Node(object):
def __init__(self, value, next=None):
self.value = value
self.next = next
def reverse(head):
temp = head
llSize = 0
while temp is not None:
llSize += 1
temp = temp.next
for i in xrange(llSize-1,0,-1):
xcount = 0
temp = head
while (xcount != i):
temp.value, temp.next.value = temp.next.value, temp.value
temp = temp.next
xcount += 1
return head
def printnodes(n):
b = True
while b == True:
try:
print n.value
n = n.next
except:
b = False
n0 = Node(1,Node(2,Node(3,Node(4,Node(5,)))))
print 'Nodes in order...'
printnodes(n0)
print '---'
print 'Nodes reversed...'
n1 = reverse(n0)
printnodes(n1)
def reverseLinkedList(head):
current = head
previous = None
nextNode = None
while current:
nextNode = current.nextNode
current.nextNode = previous
previous = current
current = nextNode
return previous
Most previous answers are correct but none of them had the complete code including the insert method before and and after the reverse so you could actually see the outputs and compare. That's why I'm responding to this question. The main part of the code of course is the reverse_list() method.
This is in Python 3.7 by the way.
class Node(object):
def __incurrent__(self, data=None, next=None):
self.data = data
self.next = next
class LinkedList(object):
def __incurrent__(self, head=None):
self.head = head
def insert(self, data):
tmp = self.head
self.head = Node(data)
self.head.next = tmp
def reverse_list(self):
current = self.head
prev = None
while current :
#create tmp to point to next
tmp = current.next
# set the next to point to previous
current.next = prev
# set the previous to point to current
prev = current
#set the current to point to tmp
current = tmp
self.head = prev
def print(self):
current = self.head
while current != None:
print(current.data,end="-")
current = current.next
print(" ")
lk = LinkedList()
lk.insert("a")
lk.insert("b")
lk.insert("c")
lk.print()
lk.reverse_list()
lk.print()
output:
c-b-a-
a-b-c-
Following is the generalized code to reverse a singly linked list, where head is given as function's argument:
def reverseSll(ll_head):
# if head of the linked list is empty then nothing to reverse
if not ll_head:
return False
# if only one node, reverse of one node list is the same node
if not ll_head.next:
return ll_head
else:
second = ll_head.next # get the second node of the list
ll_head.next = None # detach head node from the rest of the list
reversedLL = reverseSll(second) # reverse rest of the list
second.next = ll_head # attach head node to last of the reversed list
return reversedLL
Let me explain what I am doing here:
1) if head is null or head.next is null(only one node left in the list) return node
2) else part: take out 1st node, remove its link to rest of the list, reverse rest of the list(reverseSll(second)) and add 1st node again at last and return the list
Github link for the same
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList :
def __init__(self):
self.head = None
def add(self, data):
node = Node(data)
if not self.head:
self.head = node
else:
current = self.head
while current.next != None:
current = current.next
current.next = node
def printList(self):
value = []
if not self.head:
print("liss is Empty")
else:
current = self.head
while current:
value.append(current.data)
current = current.next
print(value)
# this func start reverse list from the last to first
def reverseLinkedList(self,node1,node2):
if self.head == None:
print("list Empty")
else:
# when we reach the last of list we link head with the last element and we disconnect head with second element that will make first element in the last of the list
if node2 == None and node1 != None:
self.head.next = None
self.head = node1
return
else:
self.reverseLinkedList(node1.next, node2.next )
node2.next = node1
ln = LinkedList()
ln.add(1)
ln.add(2)
ln.add(3)
ln.add(4)
ln.add(5)
ln.add(6)
ln.add(7)
ln.add(8)
ln.add(9)
ln.printList()
ln.reverseLinkedList(ln.head,ln.head.next)
print("after first reverse")
ln.printList()
# after i reverse list I add new item to the last
ln.add(0)
print("after add new element to the last of the list")
ln.printList()
print("after second reverse")
# i made second reverse to check after I add new element if my function work perfectly
ln.reverseLinkedList(ln.head,ln.head.next)
ln.printList()
Output :
[1, 2, 3, 4, 5, 6, 7, 8, 9]
after first reverse
[9, 8, 7, 6, 5, 4, 3, 2, 1]
after add new element to the last of the list
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
after second reverse
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Efficient way to reverse linkedlist is discussed in the below steps. Approach to reverse the linking.
Use a variable curr and equal it to head.
Use a variable prev and equal it to None.
Apply the loop with the condition that loop will run till curr is not None and in this condition use another variable next which is equal to curr.next. This will be used to get hold of next node. Now make curr.next = prev. In this way the head after reversing linkedlist will point to None. Now make prev = curr and curr = next
Code snippet
def reverse_linked_list(head):
# corner case
if head == None:
return
curr = head
# reason being orginal head after reversing should point to None
prev = None
while curr is not None:
next = curr.next
curr.next = prev
prev = curr
curr = next
# prev is returned because both curr and next will be None after reversing
return prev
There is another way to perform the task which will take time complexity as theta(n) and space complexity as theta(n). This is a recursive solution and steps are as below
Step 1: Apply the recursion for n -1 node from the end side. This means reverse the list leaving the first node.
Step 2: Link the first node with all nodes obtained from step 1 in reverse order
Code
def reverse_linked_list_recursion(head):
# corner case
if head == None:
return
if head.next == None:
return head
rest_head = reverse_linked_list_recursion(head.next)
rest_tail = head.next
rest_tail.next = head
head.next = None
return rest_head
U can use mod function to get the remainder for each iteration and obviously it will help reversing the list . I think you are a student from Mission R and D
head=None
prev=None
for i in range(len):
node=Node(number%10)
if not head:
head=node
else:
prev.next=node
prev=node
number=number/10
return head