Delete last node in linked list - python

I am implementing deletion of last node in linked list using Python. Below is my code:
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
# Iterating till the last Node
while temp.next != None:
temp = temp.next
temp = None
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)
However, in output I'm still getting the complete linked list.
10 20 30
How is it printing 30 when the last node is already set to temp = None?

Well, your linked list is:
10 -> 20 -> 30
^head
Your iteration:
10 -> 20 -> 30
^head ^temp
Then when you do temp = None, just means(you just assign None to temp):
10 -> 20 -> 30 None
^head ^temp
A correct way is when you iterate on 20, do temp.next = None to remove the reference to the last node. So your code might be:
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
# Iterating till the last Node
while temp.next.next != None:
temp = temp.next
temp.next = None
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)
This code would work when your linked list contain at least two elements. When there is only one element, this will raise exception. I would recommend you use a dummy head node which next point to the real head node.

#Another way of solving
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
prev=None #creating the value of previous element
# Iterating till the last Node
while temp.next != None:
prev=temp #updating for every iteration
temp = temp.next
prev.next = None #returning as NONE value
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)

Related

Why does my code to reverse a Linked List only return the first node?

I am trying to reverse a linked list with the following code. I have traced it out on paper and it seems to work, but it is failing most tests- can someone let me know where it is going wrong please?
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def reverseLinkedList(head):
curr,prev,nex = head,None,head.next
while nex:
curr.next = prev
prev = curr
curr = nex
nex = nex.next
return curr
When your while loop exits, curr.next is still None, therefore it is returning only the head of the reversed linked-list.
Just add a line curr.next = prev after the while loop, then it will work fine.
So the code of the reverseLinkedList function will be:
def reverseLinkedList(head):
curr,prev,nex = head,None,head.next
while nex:
curr.next = prev
prev = curr
curr = nex
nex = nex.next
curr.next = prev
return curr
Example for better explaination:
Let's assume our linked-list is: 1 --> 2 --> 3
After execution of code linked-list becomes: 1 <-- 2 3 <-- curr
There is no link between 2 and 3, but your prev is pointing to 2.
so executing a line curr.next = prev will make the linked list:
1 <-- 2 <--3 <--curr
You can use Python's multi-variable assignments to implement the reversal (you just have to be careful with the order of variables):
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def __repr__(self):
return str(self.value) + (self.next and f"-->{self.next}" or "")
def reverseLinkedList(head):
newHead = None
while head:
newHead,newHead.next,head = head,newHead,head.next
return newHead
Output:
h = t = LinkedList(1)
for v in range(2,10):
t.next = LinkedList(v)
t = t.next
print(h)
1-->2-->3-->4-->5-->6-->7-->8-->9
rh = reverseLinkedList(h)
print(rh)
9-->8-->7-->6-->5-->4-->3-->2-->1

Error: Merge two sorted linkedlist using dummy head technique in Python

I'm trying to solve merge two sorted linkedlist problem using dummy head technique. For some reason I have an error coming from passing an argument to my dummy head holder. The output suppose to merge both linkedlist like this: 1-> 1-> 2-> 3-> 7-> None
I would be happy if you please guide which data needs to pass in my dummy head variable? Thanks in advance! This is the error I have:
dummy = LinkedList()
TypeError: __init__() missing 1 required positional argument: 'data
Here's my complete code:
class LinkedList:
def __init__(self, data):
self.data = data
self.next = None
def print_list(head: LinkedList) -> None:
while head:
print(head.data, end=" -> ")
head = head.next
print("None")
def merge_lists(headA, headB):
dummy = LinkedList()
curr = dummy
while headA != None and headB != None:
if headA.data < headB.data:
curr.next = headA
headA = headA.next
else:
curr.next = headB
headB = headB.next
curr = curr.next
if headA != None:
curr.next = headA
else:
curr.next = headB
return dummy.next
node1 = LinkedList(1)
node1.next = LinkedList(2)
node1.next.next = LinkedList(7)
node2 = LinkedList(1)
node2.next = LinkedList(3)
print(merge_lists(node1, node2)) # 1-> 1-> 2-> 3-> 7-> None
Since it is a dummy node, and you never ever use the data attribute of that node, you can pass anything as argument, like None:
dummy = LinkedList(None)
Alternatively, you could specify that providing an argument is optional, and define the constructor as follows:
class LinkedList:
def __init__(self, data=None):
self.data = data
self.next = None
Unrelated, but at the end of your script you have:
print(merge_lists(node1, node2))
This will print the object reference. You probably wanted to call the function you have defined for this purpose:
print_list(merge_lists(node1, node2))
If you want print to work like that, then instead of the print_list function, enrich LinkedList with an __iter__ method to ease iteration over the values in the list, and a __repr__ or __str__ method as follows:
class LinkedList:
def __init__(self, data=None):
self.data = data
self.next = None
def __iter__(self):
head = self
while head:
yield head.data
head = head.next
yield None # Optional
def __repr__(self):
return " -> ".join(map(str, self))
...and then you can do
print(merge_lists(node1, node2))
class node:
def __init__(self, data):
self.data = data
self.next = None
class linkedList:
def __init__(self):
self.head = None
def insertNode(self, data):
newnode = node(data)
if self.head is None:
self.head = newnode
else:
current = self.head
while current.next is not None:
current = current.next
current.next = newnode
def printLL(self):
current = self.head
while current.next is not None:
print(current.data, end='----->')
current = current.next
print(current.data, '------>None')
def sortLL(self):
arr=[]
current = self.head
while current.next is not None:
arr.append(current.data)
current = current.next
arr.append(current.data)
arr.sort()
self.head = None
for i in arr:
self.insertNode(i)
def mergeTwoSortedLL(l, l2):
current1 = l.head
current2 = l2.head
l3 = linkedList()
while current1 is not None and current2 is not None:
if current1.data < current2.data:
l3.insertNode(current1.data)
current1 = current1.next
else:
l3.insertNode(current2.data)
current2 = current2.next
if current1 is None:
while current2.next is not None:
l3.insertNode(current2.data)
current2 = current2.next
l3.insertNode(current2.data)
else:
while current1.next is not None:
l3.insertNode(current1.data)
current1 = current1.next
l3.insertNode(current1.data)
return l3
l = linkedList()
l.insertNode(9)
l.insertNode(18)
l.insertNode(11)
l.insertNode(15)
l.insertNode(1)
l.insertNode(8)
l.sortLL()
l.printLL()
l2 = linkedList()
l2.insertNode(9)
l2.insertNode(18)
l2.insertNode(11)
l2.insertNode(15)
l2.insertNode(1)
l2.insertNode(8)
l2.sortLL()
l2.printLL()
mergeTwoSortedLL(l,l2).printLL()

Delete a node in a linked list recursively

The below code deletes a node in a linked list using iteration.
Now I would like to to delete a node using recursion:
def delete(self, key):
temp = self.head
if (temp is not None):
if temp.data == key:
self.head = temp.next
temp = None
return
if temp is None:
return
while (temp is not None):
if temp.data == key:
break
prev = temp
temp = temp.next
prev.next = temp.next
temp = None
I don't see how I can make this recursive...
def deleteNode(root, key):
if not root:
return None
if root.data == key: # delete the first node of linked list
return root.next
if root.next:
next = deleteNode(root.next, key)
root.next = next
return root
Here I have attempted to correct it. You need to assign prev before break as break will exit from the loop and your prev and temp will never be assigned in some cases.
def delete(self,key):
temp=self.head
if(temp is not None):
if temp.data==key:
self.head=temp.next
temp=None
return
if temp is None:
return
while(temp is not None):
prev=temp
temp=temp.next
if temp.data==key:
break
prev.next=temp.next
temp=None
First of all, your code will run into an exception when the data is not found in the list. Secondly, it is not necessary to do temp = None just before exiting the function.
To cope with the first issue, the iterative function could be:
def deleteNode(self, key):
prev = None
node = self.head
while node and node.data != key:
prev = node
node = node.next
if node == self.head:
self.head = node.next
elif node:
prev.next = node.next
The recursive version:
def deleteNode(self, key):
def recur(node):
if node:
if node.data == key:
return node.next
node.next = recur(node.next)
return node
self.head = recur(self.head)
Considering singly linked list of integers and position(pos) 'i'.
Deleting the node present at the 'i-th' position
def deleteNodeRec(head, pos) :
#Your code goes here
if pos == 0:
return head.next
if (head.next is None):
return head
head.next = deleteNodeRec(head.next,pos-1)
return head
Reference: https://www.svastikkka.com/2022/07/delete-node-recursive.html

Merging 2 Linkedlists in python NOT working. Third Linked List created is giving me a NULL value/result after execution

I'm currently stuck on this python exercise where I have 2 LinkedLists (linked_list_1,linked_list_2) which I have to merge together in a new LinkedList. I have tried this code but it keeps giving me a null value for the third LinkedList when I need it to give me the data in both linkedLists. The function is called: merge_linked_lists(linked_list_1, linked_list_2). That's where my problem is. I would be really grateful if someone can help.
class Node:
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def __str__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.length = 0
self.head = None
def print_list(self):
node = self.head
while node is not None:
print(node, end=' ')
node = node.next
print('')
def add_at_head(self, node):
node.next = self.head
self.head = node
self.length += 1
def remove_node_after(self, node):
if node.next is not None:
temp = node.next
node.next = node.next.next
temp.next = None
self.length -= 1
def remove_first_node(self):
if self.head is None:
return
temp = self.head
self.head = self.head.next
temp.next = None
self.length -= 1
def print_backward(self):
def print_nodes_backward(node):
if node.next is not None:
print_nodes_backward(node.next)
if node is not None:
print(node, end=' ')
if self.head is not None:
print_nodes_backward(self.head)
print('')
def merge_linked_lists(linked_list_1, linked_list_2):
def merge(List_1, List_2):
head_ptr = temp_ptr = Node() # head_ptr will be the head node of the output list
# temp_ptr will be used to insert nodes in the output list
# Loop for merging two lists
# Loop terminates when both lists reaches to its end
while List_1 or List_2:
# List_1 has not reached its end
# and List_2 has either reached its end or its current node has data
# greater than or equal to the data of List_1 node
# than insert List_1 node in the ouput list
if List_1 and (not List_2 or List_1.data <= List_2.data):
temp_ptr.next = Node(List_1.data)
List_1 = List_1.next
# otherwise insert List_2 node in the ouput list
else:
temp_ptr.next = Node(List_2.data)
List_2 = List_2.next
# move temp_pointer to next position
temp_ptr = temp_ptr.next
# return output list
return head_ptr.next
merge(linked_list_1.head, linked_list_2.head)
# Test merge() function
LL1 = LinkedList()
LL1.add_at_head(Node(2))
LL1.add_at_head(Node(4))
LL1.add_at_head(Node(6))
LL1.add_at_head(Node(8))
LL2 = LinkedList()
LL2.add_at_head(Node(1))
LL2.add_at_head(Node(3))
LL2.add_at_head(Node(5))
LL2.add_at_head(Node(7))
# Merge Function
LL3 = LinkedList()
LL3.head = merge_linked_lists(LL1, LL2)
LL3.print_list()
EDIT 1:
To anyone who wants to know the output, I tried this code on my IDE (Pycharm) and it gave an empty output/result. I also tried it on pythontutor (It visuals i/o there) and I saw that linked_list_1 and linked_list_2 haven't changed but the third linked list was null. Also during the execution, the third linkedlist was able to merge them together but it had an extra node which was the first node (head) and it had NONE as data.
EDIT 2:
The code finally worked!
class Node:
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def __str__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.length = 0
self.head = None
def print_list(self):
node = self.head
while node is not None:
print(node, end=' ')
node = node.next
print('')
def add_at_head(self, node):
node.next = self.head
self.head = node
self.length += 1
def remove_node_after(self, node):
if node.next is not None:
temp = node.next
node.next = node.next.next
temp.next = None
self.length -= 1
def remove_first_node(self):
if self.head is None:
return
temp = self.head
self.head = self.head.next
temp.next = None
self.length -= 1
def print_backward(self):
def print_nodes_backward(node):
if node.next is not None:
print_nodes_backward(node.next)
if node is not None:
print(node, end=' ')
if self.head is not None:
print_nodes_backward(self.head)
print('')
def sortList(self):
#Node current will point to head
current = self.head;
index = None;
if(self.head == None):
return;
else:
while(current != None):
#Node index will point to node next to current
index = current.next;
while(index != None):
#If current node's data is greater than index's node data, swap the data between them
if(current.data > index.data):
temp = current.data;
current.data = index.data;
index.data = temp;
index = index.next;
current = current.next;
def merge_linked_lists(linked_list_1, linked_list_2):
linked_list_1.sortList()
linked_list_2.sortList()
def merge(List_1, List_2):
head_ptr = temp_ptr = Node() # head_ptr will be the head node of the output list
# temp_ptr will be used to insert nodes in the output list
# Loop for merging two lists
# Loop terminates when both lists reaches to its end
while List_1 or List_2:
# List_1 has not reached its end
# and List_2 has either reached its end or its current node has data
# greater than or equal to the data of List_1 node
# than insert List_1 node in the ouput list
if List_1 and (not List_2 or List_2.data >= List_1.data):
temp_ptr.next = Node(List_1.data)
List_1 = List_1.next
# otherwise insert List_2 node in the ouput list
else:
temp_ptr.next = Node(List_2.data)
List_2 = List_2.next
# move temp_pointer to next position
temp_ptr = temp_ptr.next
# return output list
return head_ptr.next
return merge(linked_list_1.head, linked_list_2.head)
# Test merge() function
LL1 = LinkedList()
LL1.add_at_head(Node(2))
LL1.add_at_head(Node(4))
LL1.add_at_head(Node(6))
LL1.add_at_head(Node(8))
LL2 = LinkedList()
LL2.add_at_head(Node(1))
LL2.add_at_head(Node(3))
LL2.add_at_head(Node(5))
LL2.add_at_head(Node(7))
# Merge Function
LL3 = LinkedList()
LL3.head = merge_linked_lists(LL1, LL2)
LL3.print_list()
Ps: I also made another code which also worked.
class Node:
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def __str__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.length = 0
self.head = None
def sortList(self):
# Node current will point to head
current = self.head;
index = None;
if (self.head == None):
return;
else:
while (current != None):
# Node index will point to node next to current
index = current.next;
while (index != None):
# If current node's data is greater than index's node data, swap the data between them
if (current.data < index.data):
temp = current.data;
current.data = index.data;
index.data = temp;
index = index.next;
current = current.next;
def print_list(self):
node = self.head
while node is not None:
print(node, end=' ')
node = node.next
print('')
def add_at_head(self, node):
node.next = self.head
self.head = node
self.length += 1
def remove_node_after(self, node):
if node.next is not None:
temp = node.next
node.next = node.next.next
temp.next = None
self.length -= 1
def remove_first_node(self):
if self.head is None:
return
temp = self.head
self.head = self.head.next
temp.next = None
self.length -= 1
def print_backward(self):
def print_nodes_backward(node):
if node.next is not None:
print_nodes_backward(node.next)
if node is not None:
print(node, end=' ')
if self.head is not None:
print_nodes_backward(self.head)
print('')
def merge_linked_lists(linked_list_1, linked_list_2):
linked_list_1.sortList()
linked_list_2.sortList()
LL3 = LinkedList()
node = linked_list_2.head
node1 = linked_list_1.head
if node is None and node1 is None:
return LL3
while True:
if node1 is None:
LL3.add_at_head(Node(node.data))
node = node.next
if node is None:
return LL3
else:
continue
if node is None:
LL3.add_at_head(Node(node1.data))
node1 = node1.next
if node1 is None:
return LL3
else:
continue
if node.data > node1.data:
LL3.add_at_head(Node(node.data))
node = node.next
if node1.data > node.data:
LL3.add_at_head(Node(node1.data))
node1 = node1.next
return LL3
# Test merge() function
# Linked List with even numbers
LL1 = LinkedList()
LL1.add_at_head(Node(2))
LL1.add_at_head(Node(4))
LL1.add_at_head(Node(6))
LL1.add_at_head(Node(8))
# Linked List with odd numbers
LL2 = LinkedList()
LL2.add_at_head(Node(1))
LL2.add_at_head(Node(3))
LL2.add_at_head(Node(5))
LL2.add_at_head(Node(7))
# Merge Function
LL3 = LinkedList()
LL3 = merge_linked_lists(LL1, LL2)
LL3.print_list()
Your merge function has no return statement:
Change:
merge(linked_list_1.head, linked_list_2.head)
to:
return merge(linked_list_1.head, linked_list_2.head)
Another issue is that the sort order of your two input lists is descending, while your merge function assumes they are sorted ascending. So as a result your merged list is not sorted.
So either initialise your lists to be ascending in order (remember you insert values in reversed order) or change <= to >= in your merge function.

Reversing a linked list in python

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

Categories

Resources