Merging Multiple sorted linkedlists into One - python

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()

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()

Python dictionary with values as singly linked lists

I have been trying to create a Python dictionary with values as singly linked lists. My code looks okay resulting correct keys. However each key yield the same value, do not know why. Please reply if you have any solution, code has been given below.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
tail = self.head
while tail.next:
tail = tail.next
tail.next = new_node
def create_two_ll(self, lists):
ll_dict = {}
for i in range(len(lists)):
for data in lists[i]:
self.append(data)
ll_dict[f"ll{i}"] = ll
print(ll_dict)
print(ll_dict["ll0"].head.next.next.next.data)
print(ll_dict["ll1"].head.next.next.next.data)
return ll_dict
if __name__ == "__main__":
ll = LinkedList()
ll.create_two_ll([[1,3,5], [2,4,6]])
Output (wrong):
{'ll0': <__main__.LinkedList object at 0x7feead82c850>}
{'ll0': <__main__.LinkedList object at 0x7feead82c850>, 'll1': <__main__.LinkedList object at 0x7feead82c850>}
2
2
i solved it another way but im not sure its ok
i hope it'll trigger better way in your mind
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
tail = self.head
while tail.next:
tail = tail.next
tail.next = new_node
def create_two_ll(self, lists):
ll_dict = {}
for i in range(len(lists)):
for data in lists[i]:
self.append(data)
ll_dict[f"ll{i}"] = data
print(ll_dict)
return ll_dict
if __name__ == "__main__":
ll = LinkedList()
ll.create_two_ll([[1,3,5], [2,4,6],[7,9,11]])

How to merge linked lists without sorting? - Python

How can I create a simple function that merges two linked lists in a way that allows me to do the following with something like 'merge(self, other)', also I do not need my merged list to necessarily be sorted - I would like the merge function to simply just add and I've included driver code to give an idea
ls = [2,3,4,5]
ls2 = [42, 17]
ls.merge(ls2) # should change ls to [2,3,4,5,42,17]
ls2.head.data = 24 # should change ls2 to [24,17] and ls to [2,3,4,5,24,17]
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def merge_sorted(self, llist):
p = self.head
q = llist.head
s = None
if not p:
return q
if not q:
return p
if p and q:
if p.data <= q.data:
s = p
p = s.next
else:
s = q
q = s.next
new_head = s
while p and q:
if p.data <= q.data:
s.next = p
s = p
p = s.next
else:
s.next = q
s = q
q = s.next
if not p:
s.next = q
if not q:
s.next = p
return new_head
llist_1 = LinkedList()
llist_2 = LinkedList()
llist_1.append(1)
llist_1.append(5)
llist_1.append(7)
llist_1.append(9)
llist_1.append(10)
llist_2.append(2)
llist_2.append(3)
llist_2.append(4)
llist_2.append(6)
llist_2.append(8)
llist_1.merge_sorted(llist_2)
llist_1.print_list()
I guess append is a better name for simple merge.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None # If we don't store tail, `append` would be O(n)
def append(self, other): # `other` is also a `LinkedList`
if self.head:
self.tail.next = other.head
self.tail = other.tail
else:
self.head = other.head
self.tail = other.tail
To allow for an efficient append and merge implementation you would need to add the tail attribute to your linked list implementation
I would vote against a print_list method, because printing should not be managed by such a class. Instead provide a method that will give a string representation of the list, and let the main program decide whether to print that.
Here is how that could work:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None # <-- add this to have an efficient append/merge method
def append(self, data):
node = Node(data)
if not self.head: # When this list is empty
self.head = node
else:
self.tail.next = node
self.tail = node
def merge(self, llist):
if not self.head: # When this list is empty
self.head = llist.head
else:
self.tail.next = llist.head
self.tail == llist.tail
def __iter__(self): # To facilitate any need to iterate through the list
node = self.head
while node:
yield node.data
node = node.next
def __str__(self): # Don't make a print method; instead provide a string
return "->".join(map(str, self)) # This calls self.__iter__()
llist_1 = LinkedList()
llist_2 = LinkedList()
llist_1.append(1)
llist_1.append(5)
llist_1.append(7)
llist_1.append(9)
llist_1.append(10)
llist_2.append(2)
llist_2.append(3)
llist_2.append(4)
llist_2.append(6)
llist_2.append(8)
llist_1.merge(llist_2)
print(llist_1) # Only call `print` here

Insert after another item in linked list in 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

Python insert node function

I am having a really hard time understanding how to properly fix my insert node function. I am not receiving any errors but I am also not displaying the list.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class Solution:
def display(self, head):
current = head
while current:
print current.data,
current = current.next
def insert(self, head, data):
self.head = head
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
new_node.next = self.head
self.head = new_node
mylist = Solution()
T = int(input())
head = None
for i in range(T):
data = int(input())
head = mylist.insert(head, data)
mylist.display(head)
Your insert() didn't return anything. So head will be None if you assign returned value to it.
I think this is you want
class Node:
def __init__(self, data):
self.data = data
self.next = None
class Solution:
def __init__(self):
self.head = None
def display(self):
current = self.head
while current:
print current.data,
current = current.next
def insert(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
new_node.next = self.head
self.head = new_node
mylist = Solution()
T = int(input())
for i in range(T):
data = int(input())
mylist.insert(data)
mylist.display()

Categories