Single Link List in Python Add, Remove, Insert - python

I'm trying to achieve a singly linked list with add, remove and insert methods. I'm confused with the insertion method.
class Node(object):
def __init__(self, data, next):
self.data = data
self.next = next
class SingleList(object):
head = None
tail = None
def printList(self):
print "Link List:"
current_node = self.head
while current_node is not None:
print current_node.data, " --> ",
current_node = current_node.next
print None
def add(self, data):
node = Node(data, None)
if self.head is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
def insert(self, before, nextdata):
#nextdata is to be inserted before 'before'
#before is actually a data
#but it has dif name in this def to avoid confusion with 'data'
current_node = self.head
previous_node = None
while current_node is not None:
if current_node.data == before:
if previous_node is not None:
current_node.next = current_node
previous_node = current_node
current_node = current_node.next
def remove(self, node_value):
current_node = self.head
previous_node = None
while current_node is not None:
if current_node.data == node_value:
# if this is the first node (head)
if previous_node is not None:
previous_node.next = current_node.next
else:
self.head = current_node.next
# needed for the next iteration
previous_node = current_node
current_node = current_node.next
Link List:
1 --> 2 --> 3 --> 4 --> 5 --> None
Link List:
3 --> 4 --> 6 --> 10 --> None
For example if I'm trying to do insert (4,9) which inserts number 9 before 4.
s = SingleList()
s.add(1)
s.add(2)
s.add(3)
s.add(4)
s.add(5)
s.printList()
s.add(6)
s.add(10)
s.remove(5)
s.remove(2)
s.remove(1)
s.printList()
s.insert(4,9)
s.printList()
Any help will do, snippets, advice anything not spoon feeding. Thanks!

You have to rewrite your insert as:
def insert(self, before, nextdata):
#nextdata is to be inserted before 'before'
#before is actually a data
#but it has dif name in this def to avoid confusion with 'data'
current_node = self.head
previous_node = None
while current_node is not None:
if current_node.data == before:
if previous_node is not None:
temp_node = current_node
current_node = Node(nextdata, temp_node)
previous_node.next = current_node
else:
new_node = Node(nextdata, current_node)
self.head = new_node
break
previous_node = current_node
current_node = current_node.next
This will take care of it. When you insert the new node you have to break your loop otherwise it will be infinite.

Related

pop method LinkedList Class

I have implemented the LinkedList class: I need to implement the pop() which takes no parameter. The method removes and returns the item at the end of the linked list. If the list is empty it returns None and does nothing.
class LinkedList:
def __init__(self):
self.head = None
self.count = 0
def is_empty(self):
return self.count == 0
def size(self):
return self.count
def add(self, item):
new_node = Node(item)
new_node.set_next(self.head)
self.head = new_node
self.count += 1
def search(self, item):
current = self.head
while current != None:
if current.get_data() == item:
return True
else:
current = current.get_next()
return False
def remove(self, item):
found = False
current = self.head
previous = None
while current != None and not found:
if current.get_data() == item:
found = True
else:
previous = current
current = current.get_next()
if found:
if previous == None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.count -= 1
else:
raise ValueError("remove(" + str(item) + "). " + str(item) + " is not in list")
def clear(self):
self.head = None
self.count = 0
def __str__(self):
temp = self.head
if(temp != None):
output ="Head"
while (temp != None):
output = output+" --> "+str(temp.data)
temp = temp.next
return output
else:
return "Head --> None"
def append(self, item):
new_node = Node(item)
if self.head is None:
self.head = new_node
return
last = self.head
while(last.next):
last = last.next
last.next = new_node
def pop(self): #Problem here
if self.head is None:
return None
else:
popnode = self.head
self.head = self.head.next
popnode.next = None
return popnode.data
Test:
a_list = LinkedList()
a_list.add(1)
a_list.add(2)
a_list.add(3)
print(a_list)
print("Removed item:",a_list.pop())
print("Removed item:",a_list.pop())
print(a_list)
Expected Output:
Head --> 3 --> 2 --> 1
Removed item: 1
Removed item: 2
Head --> 3
Recd Output:
Head --> 3 --> 2 --> 1
Removed item: 3
Removed item: 2
Head --> 1
Test:
a_list = LinkedList()
a_list.append(1)
a_list.append(2)
a_list.append(3)
print(a_list)
print("Removed item:",a_list.pop())
print("Removed item:",a_list.pop())
print(a_list)
Expected output:
Head --> 1 --> 2 --> 3
Removed item: 3
Removed item: 2
Head --> 1
Recd output:
Head --> 1 --> 2 --> 3
Removed item: 1
Removed item: 2
Head --> 3
Here's a simplified pop() method which does what you require -
def pop(self): #Problem here
# Empty LinkedList
if self.head is None:
return None
# There is a single node in the LinkedList = head, read data and delete it
if self.head.next is None:
data = self.head.data
self.head = None
return data
# there are 2 or more nodes in the LinkedList
secondlast = self.head
while (secondlast.next.next):
secondlast = secondlast.next
# found the second last node
# read the data of the last node and then delete it, by setting secondlast.next = None
data = secondlast.next.data
secondlast.next = None
return data
another approach using a temporary dummy node to simplify case when there is a single node in the LinkedList-
def pop(self): #Problem here
# Empty linkedlist
if self.head is None:
return None
# create a dummy secondlast node
secondlast = Node(-1)
secondlast.next = self.head
while (secondlast.next.next):
secondlast = secondlast.next
data = secondlast.next.data
secondlast.next = None
return data
In your LinkedList, both append() and pop() methods are O(n), since you need to traverse through whole LinkedList to do those operations. Consider adding a new property self.tail(or self.secondlast) to the LinkedList which keeps track of the last node in the LinkedList. It would help in simplifying the code and making both append() and pop() operations O(1)
Just track popnode.next when become None and at the same time store previous item, when popnode.next become None, Just put next of prev None, and return data of popnode.next:
def pop(self): # Problem here
if self.head is None:
return None
elif self.head.next == None:
d = self.head.data
self.head = None
return d
else:
popnode = self.head
prev = popnode
while popnode.next:
prev = popnode
popnode = popnode.next
prev.next = None
return popnode.data
The output of:
a_list = LinkedList()
a_list.add(1)
a_list.add(2)
a_list.add(3)
print(a_list)
print("Removed item:", a_list.pop())
print("Removed item:", a_list.pop())
print("Removed item:", a_list.pop())
print(a_list)
Will be:
Head --> 3--> 2--> 1
Removed item: 1
Removed item: 2
Removed item: 3
Head None

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

Remove Duplicates from unsorted Linked list(python)

In my last code for removing duplicates, the method removeDup isn't working.
The last print(ll.display()) is printing the previous linked list.
I was hoping it to print only unique nodes. What am I missing in removeDups method?
I can't figure out. What is happening in the code here?
class Node:
def __init__(self,data = None):
self.data = data
self.next = None
def __repr__(self):
return self.data
class LList:
def __init__(self):
self.head = None
def display(self):
current = self.head
node = []
while current != None:
node.append(current.data)
current = current.next
return node
def append(self, data):
elem = Node(data)
if self.head == None:
self.head = elem
else:
current = self.head
while current.next != None:
current = current.next
current.next = elem
def add_atFront(self, data):
elem = Node(data)
if self.head == None:
self.head = elem
else:
elem.next = self.head
self.head = elem
def removeDup(self):
current = self.head
previous = None
elems = []
while current != None:
if current.data in elems:
previous.next= current.next
else:
elems.append(current.data)
previous = current
current = current.next
ll= LList()
print(ll.display())
ll.append(65)
ll.append(7)
ll.add_atFront('65')
ll.add_atFront('Bare')
ll.insert('10',0)
ll.insert('7',2)
print(ll.display())
ll.removeDup()
print(ll.display())
Your removeDup works fine, the issue is that 65 and '65' are not duplicates, so you should not expect removeDup to dedup them. The same goes for 7 and '7'. Also, note you never defined the insert method, but I'll assume that's just a copy error.

LinkedList delete functionality is deleting 2 nodes

I'm creating my own linkedList implementation and am somehow deleting 2 nodes at once. I do not understand why. I have tried deleting different integers and it seems to really like to delete the second entry in the list.
When I don't use the delete method the list traverses correctly. This leads me to believe that I am deleting incorrectly. I am keeping track of the previous node with the place_node various.
class LinkedList:
def __init__(self):
self.head = None
def prepend(self,data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def traversal(self):
temp = self.head
while temp is not None:
print(temp.data)
temp = temp.next
def append(self,data):
new_node = Node(data)
place_node = None
temp = self.head
while temp is not None:
place_node = temp
temp = temp.next
new_node.next = place_node.next
place_node.next = new_node
def delete(self,data):
new_node = Node(data)
temp = self.head
while temp is not None:
if temp.data == data:
break
place_node = temp
temp = temp.next
place_node.next = temp.next
class Node:
def __init__(self,data):
self.data = data
self.next = None
ehren = LinkedList()
ehren.prepend(5)
ehren.prepend(3)
ehren.prepend(8)
ehren.append(6)
print(" delete the number")
ehren.delete(6)
print("linked list***********")
ehren.traversal()
The delete method should be implemented like this:
def delete(self, data):
prev = None
temp = self.head
while temp is not None:
if temp.data == data:
if prev is None: # Handle the case when we are deleting the head which has no previous node
self.head = self.head.next
else:
prev.next = temp.next
break
prev = temp
temp = temp.next
Since this is a singly-linked-list, you need to keep track of the node before the target, and to delete means to set the next pointer of the previous node to the next pointer of the node to be deleted, thus making the selected node disappear.

Remove method in Python LinkedList using an index

class Node(object):
def __init__(self, data, next):
self.data = data
self.next = next
class LinkedList(object):
head = None
tail = None
def print_list(self):
node = self.head
while node:
print node.data,
node = node.next
def add_front(self, data):
node = Node(data, None)
if self.head is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
def remove(self, index):
curr_node = self.head
prev_node = None
while curr_node and index>=0:
if index == 0:
if prev_node is not None:
prev_node.next = curr_node.next
else:
self.head = curr_node.next
index = index - 1
prev_node = curr_node
curr_node = curr_node.next
So, I wanted to implement a remove method using index in python but it does not seem to be working. I think I'm messing something with replacing the nodes but can't figure out which one. So a little help needed here.

Categories

Resources