Python dictionary with values as singly linked lists - python

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

Related

Python linked-list issues of receiving memory addresses when printing unless double calling

I am creating a Linked List implementation and I cannot fix this error of having to double call node.val.val to print the data instead of the memory address.
Here is my implementation:
class LinkedNode:
def __init__(self, val, nxt=None):
self.val = val
self.nxt = nxt
class LinkedList:
def __init__(self, head=None):
self.head = head
def append(self, new_val):
node = LinkedNode(new_val, None)
if self.head:
curr = self.head
while curr.nxt:
curr = curr.nxt
curr.nxt = node
else:
self.head = node
def print(self):
curr = self.head
while curr:
**print(curr.val)**
curr = curr.nxt
l1 = LinkedList()
l1.append(LinkedNode(2))
l1.append(LinkedNode(3))
l1.append(LinkedNode(4))
l1.print()
When the line in the print function is "print(curr.val)", the function prints memory addresses. When the line is "print(curr.val.val)", the function prints 2,3,4.
Does anyone have a possible solution?
You were passing a LinkedNode() object as an argument to .append() function:
class LinkedNode:
def __init__(self, value, nxt=None):
self.val = value
self.nxt = nxt
class LinkedList:
def __init__(self, head=None):
self.head = head
def append(self, new_val):
node = LinkedNode(new_val, None) #Creation of LinkedNode from integer
if self.head:
curr = self.head
while curr.nxt:
curr = curr.nxt
curr.nxt = node
else:
self.head = node
def print(self):
curr = self.head
while curr:
print(curr.val)
curr = curr.nxt
l1 = LinkedList()
l1.append(2) #Argument must be integer, not LinkedNode(integer)
l1.append(3) #Because you are already converting integer to LinkedNode on append function
l1.append(4)
l1.print()
Output:
2
3
4
Because in these lines you are creating LinkedNode objects not values!
l1.append(LinkedNode(2))
l1.append(LinkedNode(3))
l1.append(LinkedNode(4))
After that, you created a new LinkedNode(LinkedNode(2), None) within the scope of the append function.
Change it to:
l1.append(2)
l1.append(3)
l1.append(4)

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

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

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