Insert after another item in linked list in python - python

I am trying to insert an item after another one but my code doesn't work. The below function insert_after_another doesn't work.
class LinkedList:
def __init__(self):
self.head = None
def insert_end(self,data):
x = Node(data)
if self.head == None:
self.head = x
return
temp = self.head
while(temp.next != None):
temp = temp.next
temp.next = x
def insert_after_another(self,old_data,new_data):
t_old = Node(old_data)
d_new = Node(new_data)
temp = self.head
while(temp):
if temp.data == old_data:
d_new.next = t_old.next
t_old.next = d_new
temp = temp.next
class Node:
def __init__(self,data):
self.data = data
self.next = None
if __name__=='__main__':
llist = LinkedList()
llist.insert_end(3)
llist.insert_end(32)
llist.insert_after_another(3,13)
I am not getting any result when I try to print the data.

d_new.next = t_old.next
in this line t_old.next pointing to nothing nor there is a pointer to it, it is just a node you created before.
def insert_after_another(self,old_data,new_data):
d_new=Node(new_data)
temp=self.head
while(temp):
if temp.data==old_data:
d_new.next = temp.next
temp.next = d_new
break
This may work I think.
You just need two swaps only,
The new node should point the old node's next and
the old node should point to the new one.

This will be able to resolve your problem. Consider having correct identations and renaming your method.
def insert_after_value(self, old_data, new_data):
if self.head is None:
return
if self.head.data == old_data:
self.head.next = Node(new_data, self.head.next)
return
temp = self.head
while temp:
if temp.data == old_data:
temp.next = Node(new_data, temp.next)
break
temp = temp.next

Related

Why I'm getting this error "AttributeError: 'linkList' object has no attribute 'data'" Merge Sorted link list python

Why I am getting this error? I have written all corrected but still not resolved.
Reversing the link list with optimal solution. Python programming
File "d:\DSA_Parctice\3_MonthsDSA\LinkList\ReverseLinkList.py", line 74, in
mergeTwoSortedLinkListOptimize
if list2.data <= list1.data:
AttributeError: 'linkList' object has no attribute 'data'
class Node:
def __init__(self,data):
self.data=data
self.next=None
class linkList:
def __init__(self):
self.Head=None
def insertAtBeg(self,data):
newNode = Node(data)
if self.Head == None:
self.Head = newNode
return
temp=self.Head
self.Head=newNode
self.Head.next=temp
def reverseLinkList(self):
preNode=None
currHead=self.Head
nextNode=self.Head
while currHead!=None:
nextNode=currHead.next
currHead.next=preNode
preNode=currHead
currHead=nextNode
self.Head=preNode
def printLinkList(self):
if self.Head==None:
print("Link List is Empty")
else:
temp=self.Head
while temp!=None:
print(temp.data, end=" ")
temp=temp.next
def mergeTwoSortedLinkListOptimize(list1,list2):
mergeList=Node(0)
mergeList.next = list1
while True:
if list1 is None:
list1 = list2
break
if list2 is None:
break
if list2.data <= list1.data:
temp = list1
list1= list2
list2 = list2.next
list1.next= temp
else: list1= list1.next
return mergeList.next
llist1=linkList()
llist1.insertAtBeg(3)
llist1.insertAtBeg(5)
llist1.insertAtBeg(6)
llist1.insertAtBeg(8)
llist1.insertAtBeg(9)
llist1.insertAtBeg(10)
llist2 = linkList()
llist2.insertAtBeg(1)
llist2.insertAtBeg(6)
llist2.insertAtBeg(7)
llist2.insertAtBeg(15)
llist1.reverseLinkList()
llist2.reverseLinkList()
llist1.printLinkList()
print()
llist2.printLinkList()
llist1=llist1.mergeTwoSortedLinkListOptimize(llist2)
llist1.printLinkList()
# I tried also like this "if temp1[0].data <= temp2[0].data:" but not resolved
# Why I am getting this error i have written all corrected but still not resolved.
File "d:DSA\LinkList\ReverseLinkList.py", line 74, in mergeTwoSortedLinkListOptimize
if list2.data <= list1.data:
AttributeError: 'linkList' object has no attribute 'data'
Please help me I am trying from two days
You are approaching this wrong.
mergeList=Node(0) this doesn't make sense. This should be an instance of linkList and not a standalone Node.
list1.data does not exist because it's a linkList object. See the definition of your linkList class. It has no member other than self.Head.
Your merging strategy is wrong.
mergeTwoSortedLinkListOptimize should be a separate utility function and should not be a member of linkList class because its job is to combine two linkList objects. So, it does not make sense to make it a member of the linkList class.
The fixed code is given below.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class linkList:
def __init__(self):
self.Head = None
def insertAtBeg(self, data):
newNode = Node(data)
if self.Head == None:
self.Head = newNode
return
temp = self.Head
self.Head = newNode
self.Head.next = temp
def reverseLinkList(self):
preNode = None
currHead = self.Head
nextNode = self.Head
while currHead != None:
nextNode = currHead.next
currHead.next = preNode
preNode = currHead
currHead = nextNode
self.Head = preNode
def printLinkList(self):
if self.Head == None:
print("Link List is Empty")
else:
temp = self.Head
while temp != None:
print(temp.data, end=" ")
temp = temp.next
def mergeTwoSortedLinkListOptimize(list1: linkList, list2: linkList):
# result linked list
mergeList = linkList()
# if either linked list is None, nothing to do other than returning the
# other list
if list1 is None:
mergeList = list2
if list2 is None:
mergeList = list1
# if neither is None, we can perform some comparisons
if list1 is not None and list2 is not None:
list1_current_loc = list1.Head
list2_current_loc = list2.Head
while True:
# if at the last node (node.next is None), break
if list1_current_loc is None or list2_current_loc is None:
break
# compare and put the data in the result linked list
if list1_current_loc.data <= list2_current_loc.data:
mergeList.insertAtBeg(list1_current_loc.data)
list1_current_loc = list1_current_loc.next
else:
mergeList.insertAtBeg(list2_current_loc.data)
list2_current_loc = list2_current_loc.next
# copy over any remaining items
while list1_current_loc is not None:
mergeList.insertAtBeg(list1_current_loc.data)
list1_current_loc = list1_current_loc.next
while list2_current_loc is not None:
mergeList.insertAtBeg(list2_current_loc.data)
list2_current_loc = list2_current_loc.next
return mergeList
llist1 = linkList()
llist1.insertAtBeg(3)
llist1.insertAtBeg(5)
llist1.insertAtBeg(6)
llist1.insertAtBeg(8)
llist1.insertAtBeg(9)
llist1.insertAtBeg(10)
llist2 = linkList()
llist2.insertAtBeg(1)
llist2.insertAtBeg(6)
llist2.insertAtBeg(7)
llist2.insertAtBeg(15)
llist1.reverseLinkList()
llist2.reverseLinkList()
llist1.printLinkList()
print()
llist2.printLinkList()
print()
llist1 = mergeTwoSortedLinkListOptimize(llist1, llist2)
llist1.printLinkList()

How to retrieve the first added node when a LinkedList is created?

I have created a linkedlist in Python using below classes:
class: Node
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
class LinkedList:
def __init__(self):
self.head = None
def insert_at_beginning(self, data):
temp = Node(data)
if self.head is None:
self.head = temp
else:
temp.next = self.head
self.head = temp
def insert_at_end(self, data):
temp = Node(data)
if self.head is None:
self.head = temp
else:
curr = self.head
while curr.next is not None:
curr = curr.next
curr.next = temp
def insert_at_position(self, pos, data):
temp = Node(data)
if self.head is None:
self.head = temp
else:
curr = self.head
i = 1
while i < pos:
curr = curr.next
i += 1
temp.next = curr.next
curr.next = temp
def traverse_list(self):
if self.head is None:
print('List is empty')
else:
curr = self.head
while curr.next is not None:
print(curr.data)
curr = curr.next
Below is the order I am calling the insertion methods.
ll = LinkedList()
ll.head = Node(1)
ll.insert_at_beginning(data=10)
ll.insert_at_beginning(data=11)
ll.traverse()
The elements printed in the output are: 11 & 10 which are the ones I inserted but I don't see the value 1 which is a node I added in the beginning.
Is there any logic I missed here that is making the first value skip or not being considered ?
Your problem comes from while curr.next is not None: in traverse_list(). Assuming you're pointing your last node, its next node is obviously None. Therefore, it will stop the loop before printing the last node's data.
You can try this:
def traverse_list(self):
if self.head is None:
print('List is empty')
else:
curr = self.head
while curr is not None:
print(curr.data)
curr = curr.next

LinkedList print and moving elements to another LinkedList

From list first I should do LinkedList and put elements into it (I did that). From that list I have to move all not string elements (integers) to another LinkedList and print them also.
Initialisation:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList(object):
def __init__(self):
self.head = None
self.tail = None
self.size = 0
def append(self,new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
last = self.head
while(last.next):
last = last.next
last.next = new_node
def Lista(lista):
linked = LinkedList()
for element in lista:
linked.append(element)
return linked
Function for print and function(izdvoji) to move elements to another linkedlist:
def ispis(self):
temp = self.head
while (temp):
print (temp.data)
temp = temp.next
print("------")
def izdvoji(self):
linked = LinkedList()
temp = self.head
while(temp):
if isinstance (temp.data, str):
linked.append(temp.data)
temp = temp.next //edited
else:
temp = temp.next
if __name__ == '__main__':
L = Lista([33, "asp","oop1",5,21,"python",2,"c++"])
ispis(izdvoji(L))
ispis(L)
Result must be:
asp,oop1,python,c++
33,5,21,2
Sorry for long code but I want you to see it.
Edit function:
def izdvoji(linkedLista):
linked = LinkedList()
temp = linkedLista.head
while(temp != None):
if isinstance (temp.data, str):
linked.append(temp.data)
temp = temp.next
temp = linkedLista.head
while(temp != None):
if temp == linkedLista.head and isinstance (temp.data, str):
linkedLista.head = temp.next
print(temp.data)
if temp.next != None and isinstance (temp.next.data, str):
temp.next = temp.next.next
temp = temp.next
return linked
Output:
asp,oop1, python,c++,
33, oop1, 5, 21, 2,
The print function accepts an end parameter which defaults to "\n". You can it to be ", " to print your list.
To move your nodes from one list to another you need to do two steps
Copy the node to new list
Delete the node from old list
You did not have a delete method to handle that so I had to write delete method myself.
Delete method for linked list
def delete(self, node_data):
temp = self.head
# If list is empty
if temp is None:
return
# If the head need to be removed
if temp.data == node_data:
self.head = temp.next
return
# Iterate over the list and stops when the next node is our required node
while temp is not None and temp.next.data != node_data:
temp = temp.next
# if temp is none that means we reached the end of list
if temp is None:
return
# removing the node
temp.next = temp.next.next
def ispis(linked_list):
temp = linked_list.head
while (temp):
print(temp.data, end=", ")
temp = temp.next
print("\n------")
Output:
33, asp, oop1, 5, 21, python, 2, c++,
------
As far as copying goes. You forgot to update the temp when the if condition was true. Technically you don't need else here as well. You also need to return the list after moving the elements which you are not doing.
def izdvoji(linked_list):
linked = LinkedList()
temp = linked_list.head
while temp:
if isinstance(temp.data, str):
linked.append(temp.data) # Copy node to new list
linked_list.delete(temp.data) # delete from old list
temp = temp.next
return linked
Output:
asp, oop1, python, c++,
------
33, 5, 21, 2,
------
Main Code:
if __name__ == '__main__':
L = Lista([33, "asp","oop1",5,21,"python",2,"c++"])
ispis(izdvoji(L))
ispis(L)
Note: By convention self is only used for to refer the attributes and methods of the class. izdvoji and ispis are not class methods. So using self here makes no sense.

Merging Multiple sorted linkedlists into One

I am trying to write a program to merge two sorted linked lists.
But its not merging them.
it seems like the error is in representing head pointer.
how to represent head pointer? is my way correct.
I am facing a lot of problems using pointers pls give me some suggestions especially head pointer
merge two sorted linkedlist
class Node:
def __init__(self,data):
self.data=data
self.next =None
class linkedlist:
def __init__(self):
self.head=None
def push(self,ndata):
nnode = Node(ndata)
nnode.next = self.head
self.head = nnode
def addNodeToList(self,ndata):
nnode = Node(ndata)
if self.head is None:
self.head = nnode
return
last = self.head
while last.next is not None:
last = last.next
last.next = nnode
def printList(self):
temp = self.head
while temp is not None:
print(temp.data,end = ' ')
temp = temp.next
def merge(first,second):
dummy=linkedlist()
temp = dummy.head
temp1=first.head
temp2=second.head
while temp1 and temp2:
if temp1.data<temp2.data:
temp=temp1
temp.next=None
temp1=temp1.next
print('\n1..')
elif temp1.data>=temp2.data:
temp=temp2
temp.next=None
temp2=temp2.next
print('\n2..')
if temp1 is not None:
temp.next= temp1
print('\n3..')
else:
temp.next=temp2
print('\n4..')
print('Done')
return dummy
if __name__=='__main__':
list1=linkedlist()
list1.addNodeToList(10)
list1.addNodeToList(20)
list1.addNodeToList(30)
list1.addNodeToList(40)
list1.addNodeToList(50)
list2=linkedlist()
# Create linked list 2 : 5->15->18->35->60
list2.addNodeToList(5)
list2.addNodeToList(15)
list2.addNodeToList(18)
list2.addNodeToList(35)
list2.addNodeToList(60)
list1.printList()
print()
list2.printList()
a=merge(list1,list2)
a.printList()
Expected output is a single merged linkedlist
You already have the addNodeToList() function so why not use it?
def merge(first,second):
dummy=linkedlist()
temp1=first.head
temp2=second.head
while temp1 and temp2:
if temp1.data<temp2.data:
dummy.addNodeToList(temp1.data)
temp1=temp1.next
else:
dummy.addNodeToList(temp2.data)
temp2=temp2.next
while temp1:
dummy.addNodeToList(temp1.data)
temp1=temp1.next
while temp2:
dummy.addNodeToList(temp2.data)
temp2=temp2.next
return dummy
You are never adding to dummy in your code - you do temp = dummy.head and then you reassign temp and the dummy list is never updated. Here is an approach:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList: # classes in python must be in CamelCase
def __init__(self):
self.head = None
def push(self, ndata):
nnode = Node(ndata)
nnode.next = self.head
self.head = nnode
def addNodeToList(self, ndata):
nnode = Node(ndata)
if self.head is None:
self.head = nnode
return
last = self.head
while last.next is not None:
last = last.next
last.next = nnode
def printList(self):
temp = self.head
while temp is not None:
print(temp.data, end = ' ')
temp = temp.next
def walk_list(self):
temp = self.head
values = []
while temp is not None:
values.append(temp.data)
temp = temp.next
return values
def merge(first, second):
values1 = first.walk_list()
values1.extend(second.walk_list())
dummy = LinkedList()
for v in sorted(values1):
dummy.push(v)
return dummy
if __name__ == '__main__':
list1 = LinkedList()
list1.addNodeToList(10)
list1.addNodeToList(20)
list1.addNodeToList(30)
list1.addNodeToList(40)
list1.addNodeToList(50)
list2 = LinkedList()
# Create linked list 2 : 5->15->18->35->60
list2.addNodeToList(5)
list2.addNodeToList(15)
list2.addNodeToList(18)
list2.addNodeToList(35)
list2.addNodeToList(60)
list1.printList()
print()
list2.printList()
a = merge(list1, list2)
a.printList()

why the element not appending in linked list?

not getting expected output. Missing node with data = 6
looks like not insertAfter method properly,
cant find the issue.
pls suggest any other issue too as i am just started with data structures. is there anything need to be kept in mind while studying data structures.
class Node:
def __init__(self,data):
self.data = data
self.next = None
class LinkeList:
def __init__(self):
self.head = None
def push(self,new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def insertAfter(self,prev_node,new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
new_node.next = prev_node.next
prev_node.next = new_node
def append(self,new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
last = self.head
while last.next != None:
last = last.next
last.next = new_node
def printList(self):
temp = self.head
while temp is not None:
print(temp.data, end = " ")
temp = temp.next
if __name__ =='__main__':
llist = LinkedList()
llist.append(7)
llist.append(8)
llist.push(5)
llist.insertAfter(Node(5),6)
llist.printList()
So the issue is in this line,
llist.insertAfter(Node(5),6)
When you do insertAfter then you need to first get a Node from the current linked list, rather what you are doing is, that you create a new node, then pass it. That new node might have the same value as a . node in your linked list, but it really isn't a part of it, what you need to do is as follows
First implement a get node function, that gets a node from the linked list with the value that you want, something like this
def getNode(self, value):
temp = self.head
while temp is not None:
if temp.value == value:
return temp
else:
temp = temp.next
return None
then do this.
llist.insertAfter(llist.getNode(5),6)
Also put a check for if passed node is not None in insertAfter

Categories