Double Linked List Middle Insert doesn't work - python

import math
class Node:
def __init__(self, val, next = None, prev = None):
self.data = val
self.next = next
self.prev = prev
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self.count = 0
def StartInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.head.prev = newNode
newNode.next = self.head
self.head = newNode
self.count += 1
def EndInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
newNode.prev = self.tail
self.tail = newNode
self.count += 1
def MiddleInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
index = math.ceil(self.count/2)-1
temp = self.head
while index > 0:
temp = temp.next
index -= 1
temp.next = Node(val, temp.next)
temp.prev = Node(temp.prev.data, temp)
self.count +=1
def delete(self, val):
curNode = self.head
while curNode != None:
if curNode.data == val:
if curNode.prev != None:
curNode.prev.next = curNode.next
else:
self.head = curNode.next
if curNode.next != None:
curNode.next.prev = curNode.prev
else:
self.tail = curNode.prev
self.count -= 1
curNode = curNode.next
def reverse(self):
temp = None
current = self.head
while current != None:
temp = current.prev
current.prev = current.next
current.next = temp
current = current.prev
if temp:
self.head = temp.prev
self.tail = temp.next
def traverse(self):
s = ""
p = self.head
while p is not None:
s += str(p.data) + ' ';
p = p.next
print(s + "| count: " + str(self.count))
list = LinkedList()
list.EndInsert("a")
list.StartInsert("b")
list.StartInsert("c")
list.EndInsert("d")
list.MiddleInsert("c")
list.traverse()
list.reverse()
list.traverse()
Middle Insert gives correct return but doesn't stop. I did the same method for singly linked list but it doesn't seem to work properly for double linked list. It returns proper value but keep getting stuck at the while loop.
I am trying to figure how to connect the newNode(). Please help me by showing code and the reason I get such error.
Thank you so much for helping.

An initial error is that you are creating more Node that necessarily in your MiddleInsert method.
This can lead you to finding the error in your code.
After removing these extra creations, you should simply switch the prev and next pointers, checking that the temp is not actually the last element:
def MiddleInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
index = math.ceil(self.count/2)-1
temp = self.head
while index > 0:
temp = temp.next
index -= 1
newNode.next = temp.next
temp.next = newNode
newNode.prev = temp
if newNode.next is not None:
newNode.next.prev = newNode
self.count +=1

In a doubly linked list, you must maintain prev and next pointers. In MiddleInsert, once you have selected the element that you want to add the new node after, you must insert the new element between that one and its follower.
Let us call C the new node, A the selected node and say B=A.next. Before insertion, you have A.next == B and B.prev == A ; after insertion, you want to have
A.next == C, C.prev == A, C.next == B and B.prev == C.
Just write that in MiddleInsert (unrelated, but no need for the math module here, and for ... in range(...) is the Pythonic way for counting loops):
def MiddleInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
elif self.count == 1:
self.tail = newNode
self.head.next = newNode
newNode.prev = self.head
else:
index = (self.count-1) // 2
temp = self.head
for i in range(index):
temp = temp.next
temp.next.prev = newNode
newNode.next = temp.next
newNode.prev = temp
temp.next = newNode
self.count +=1

Related

Unable to Insert node in Circular Singly linked list

I'm not able to get the desired output in the given code. The code is about inserting nodes in the circular singly linked list. Please correct this code as per the problems stated.
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSLL:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while node:
yield node
if node.next == self.head:
print('break')
break
node = node.next
def insertnode(self, value, location):
new_node = Node(value)
# check if head is None or not
if self.head is None:
self.head = new_node
self.tail = new_node
new_node.next = self.head
else:
# At the start
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = self.head
# At the end
elif location == -1:
new_node.next = self.tail.next
self.tail.next = new_node
self.tail = new_node
else:
# At specific location
temp_node = self.head
index = 0
while index < location - 1:
# node is the last element
if temp_node.next == self.head:
break
temp_node = temp_node.next
index += 1
next_node = temp_node.next
temp_node.next = new_node
new_node.next = next_node
if temp_node.next == self.head:
self.tail == temp_node
self.tail.next = self.head
return 'The node has been successfully inserted'
cll = CircularSLL()
cll.insertnode(1,0)
cll.insertnode(3, 1)
cll.insertnode(4, 2)
cll.insertnode(5, 3)
cll.insertnode(6, 4)
print([node.value for node in call])
output = [1,3,4,5,6 ]
1st problem - when inserting at index = '0'.
cll.insertnode(10,0)
output = [10,1]
expected
output = [10,1,3,4,5,6]
2nd problem - when putting location = '-1'
cll.insertnode(30, -1)
output = [1, 30]
expected
output = [10,1,3,4,5,6,30]
With your test setup, tail is never getting set after the first node is inserted.
(Pdb) [c.value for c in cll]
[1, 3, 4, 5, 6]
(Pdb) cll.head.value
1
(Pdb) cll.tail.value
1
(Pdb) cll.head is cll.tail
True
Your first problem is you have self.tail == temp_node instead of self.tail = temp_node, so let's fix that. Still, we're not getting the expected output:
[1, 3, 4, 5, 6]
The next problem is that by the time you check if temp_node.next is self.head:, you have already set temp_node.next to be new_node. It will never be self.head. I believe you intended to check new_node.next at this point, as it is now the last element.
Simply replace
if temp_node.next == self.head:
self.tail == temp_node
self.tail.next = self.head
with
if new_node.next is self.head:
self.tail = new_node
to get
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSLL:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while node:
yield node
if node.next is self.head:
break
node = node.next
def insertnode(self, value, location):
new_node = Node(value)
# check if head is None or not
if self.head is None:
self.head = new_node
self.tail = new_node
new_node.next = self.head
else:
# At the start
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = self.head
# At the end
elif location == -1:
new_node.next = self.tail.next
self.tail.next = new_node
self.tail = new_node
else:
# At specific location
temp_node = self.head
index = 0
while index < location - 1:
# node is the last element
if temp_node.next is self.head:
break
temp_node = temp_node.next
index += 1
next_node = temp_node.next
new_node.next = next_node
temp_node.next = new_node
if new_node.next is self.head:
self.tail = new_node
return 'The node has been successfully inserted'
cll = CircularSLL()
cll.insertnode(1,0)
cll.insertnode(3, 1)
cll.insertnode(4, 2)
cll.insertnode(5, 3)
cll.insertnode(6, 4)
cll.insertnode(10,0)
cll.insertnode(30, -1)
print([node.value for node in cll])
Output:
[10, 1, 3, 4, 5, 6, 30]
I have also replaced == with is in several places to more clearly test for identity rather than equivalent values.

Python Linked List Implemention - Inserting node at nth position ? Why the code is not working?

Code Image
class Node:
def __init__(self,data):
self.data = data
self.address = None
class LinkedList:
def __init__(self):
self.start = None
def insert_at_position(self,position,data):
node = Node(data)
i = 0
temp = self.start
while(i<position-1 and temp!=None):
i +=1
temp = temp.address
t1 = node
t1.address = temp
temp = t1
You can try this below assuming 0th position is the head of the LinkedList :
def insert_at_nth_pos(self, position, data):
temp = self.start
if position == 0:
new_node = Node(data)
new_node.address = self.head
self.head = new_node
return
for i in range(1, position-1):
temp = temp.address
if temp is None:
print("Position out of Bounds")
return
if temp.address is None:
temp.address = Node(data)
else:
new_node = Node(data)
new_node.address = temp.address
temp.address = new_node

How to fix errors in singly linked list method append

I have two class a node and a linked. My error is coming from the append method located in the linkedList class.
I try to .append(10) but it does not print the 10 out only the 5 when it should be appending to the end. By chance can anyone see the error?
class Node:
def __init__(self, data):
self.data = data
self.next = None
class linkedList:
def __init__(self):
self.head = None
def append(self, data):
newNode = Node(data)
if self.head == None:
self.head = newNode
return
else:
lastNode = self.head
while lastNode.next != None:
lastNode = lastNode.next
lastNode.next = newNode
def prepend(self, data):
newNode = Node(data)
if self.head == None:
self.head = newNode
return
else:
newNode.next = self.head
self.head = newNode
def insertAfterNode(self, prevNode, data):
newNode = Node(data)
newNode.next = prevNode.next
prevNode.next = newNode
def printList(self):
curNode = self.head
while curNode.next != None:
print(curNode.data)
curNode = curNode.next
def deleteNode(self, key):
curNode = self.head
if curNode != None and curNode.data == key:
self.head = curNode.next
curNode = None
return
else:
prev = None
while curNode != None and curNode.data != key:
prev = curNode
curNode = curNode.next
if curNode == None:
print("The data is not found in the list")
return
else:
prev.next = curNode.next
curNode = None
# Testing the Linked List
linkedLst = linkedList()
linkedLst.append(5)
linkedLst.append(10)
linkedLst.printList()
linkedLst.prepend(15)
linkedLst.printList()
linkedLst.insertAfterNode(linkedLst.head.next, 6)
linkedLst.insertAfterNode(linkedLst.head.next.next, 8)
linkedLst.printList()
linkedLst.deleteNode(6)
linkedLst.deleteNode(20)
linkedLst.printList()
Expected result should be 5 10, 15 5 10, 15 6 8 5 10, 15 8 5 10, and then an error message saying it can not be deleted.
However, I am getting 5, 15 5, 15 6 8 5, 15 8 5 and it excludes the 10.
I am running on vim and have python 3.7.4
If you look at method printList, the while loop stops when curNode.next is None which is when curNode is the last node. The last node didn't get a change to be printed. The element 10 is there, it's just not getting printed.
Also, just a minor thing, it's good practice to use CapWords for class names so your code is consistent with the recommended style guide.

double linked list reverse function doesn't work

Everything else works except for the reverse function. The while loop doesn't end. I add in more details. Im so sorry. This is my second time getting help from Stack overflow.
This is the full code. Im not sure how to send the tail for reverse function.
Thank you so much. I truly appreciate all of your help.
import math
class Node:
def __init__(self, val, next = None, prev = None):
self.data = val
self.next = next
self.prev = prev
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self.count = 0
def StartInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.head.prev = newNode
newNode.next = self.head
self.head = newNode
self.count += 1
def EndInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
newNode.prev = self.tail
self.tail = newNode
self.count += 1
def MiddleInsert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
index = math.ceil(self.count/2)
temp = self.head
while index > 0:
temp = temp.next
index =- 1
temp.next = Node(val, temp.next)
temp.prev = Node(temp.prev.data, temp)
self.count +=1
def search(self, val):
p = self.head
while p is not None:
if p.data == val:
return p
p = p.next
def delete(self, val):
curNode = self.head
while curNode != None:
if curNode.data == val:
if curNode.prev != None:
curNode.prev.next = curNode.next
else:
self.head = curNode.next
if curNode.next != None:
curNode.next.prev = curNode.prev
else:
self.tail = curNode.prev
self.count -= 1
curNode = curNode.next
def reverse(self):
temp = None
current = self.head
while current != None:
temp = current.prev
current.prev = current.next
current.next = temp
current = current.prev
if temp:
self.head = temp.prev
self.tail=
def traverse(self):
s = ""
p = self.head
while p is not None:
s += str(p.data) + ' ';
p = p.next
print(s + "| count: " + str(self.count))
list = LinkedList()
list.EndInsert("a")
list.StartInsert("b")
list.StartInsert("c")
list.EndInsert("d")
list.MiddleInsert("c")
list.traverse()
print("_________________")
list.reverse()
list.traverse()

Inserting Node at a specific location python

This question is a hackerrank challenge. link here: https://www.hackerrank.com/challenges/insert-a-node-at-a-specific-position-in-a-linked-list
"""
Insert Node at a specific position in a linked list
head input could be None as well for empty list
Node is defined as
class Node(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
return back the head of the linked list in the below method.
"""
#This is a "method-only" submission.
#You only need to complete this method.
def InsertNth(head, data, position):
node = head
if position == 0:
node = Node(data)
node.data = data
node.next = head
return node
else:
while position > 0:
node = node.next
i = node.next
node.next = Node(data)
node.next.next = i
return head
my current output is 321024, but I need it to be 310542. Any help is greatly appreciated!
def InsertNth(head, data, position):
start = head
if position == 0:
return Node(data, head)
while position > 1:
head = head.next
position -= 1
head.next = Node(data, head.next)
return start
I didn't test it, but something like this should be right. You first want to save a copy of the reference to the start of the list. Then, you should check if this is being added to the front of the list, in which case you should return a new starting node with the proper value. Otherwise, you cycle through the list until you get to the position you want at which point you set the next node to have the proper value and remaining list.
def insertNodeAtPosition(head, data, position):
prev_node = head
if position == 0:
new_node = SinglyLinkedListNode(data)
new_node.next = head
return new_node
while prev_node is not None:
new_node = SinglyLinkedListNode(data)
for _ in range(position-1):
prev_node = prev_node.next
new_node.next = prev_node.next
prev_node.next = new_node
return head
We have 2 possible options.
If the data should be add in the first (position = 0) and then we should change the head pointer to the current node or
The position should be added in the k-th place and we update the list using the head.next and position-1 recursively
def insertNodeAtPosition(self, head, data, position):
if (position == 0) | (head==None):
return SinglyLinkedListNode(data, head)
else:
head.next = self.insertNodeAtPosition(head.next, data, position-1)
return head
def InsertNth(head, data, position):
node = head
i = 0
temp = Node(data)
while node is not None:
if i == at:
temp.nextnode = node.nextnode
node.nextnode = temp
break
i += 1
node = node.nextnode
class SinglyLinkedListNode:
def __init__(self, node_data):
self.data = node_data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def insertNodeAtPosition(head, data, position):
pos = 0
current_head = head
previous_head = head
while pos <= position:
if pos == position:
new_head = SinglyLinkedListNode(data)
previous_head.next = new_head
new_head.next = current_head
return head
else:
pos += 1
previous_head = current_head
current_head = current_head.next
return head
def insertNodeAtPosition(head, data, position):
currNode = head
while position > 1:
position -= 1
currNode = currNode.next
temp = currNode
node = SinglyLinkedListNode(data)
node.next = temp.next
currNode.next = node
return head
def insertNodeAtPosition(head, data, position):
positer = 0
temp = head
while temp:
if positer == position-1:
newNode = SinglyLinkedListNode(data)
newNode.next = temp.next
temp.next = newNode
break
else:
positer+=1
temp = temp.next
return head
def insert_after(self, data, pos):
new_node = Node(data)
prev = self.head
pos = pos - 1
if pos == 0:
self.insert_front(data)
return
while pos > 1:
prev = prev.next
pos -= 1
new_node.next = prev.next
prev.next = new_node
Here is a recursive solution in opposition to the naive implementation
def insertNodeAtPosition(node, data, position):
if not node:
return None
if position <= 1:
new_node = SinglyLinkedListNode(data)
new_node.next = node.next
node.next = new_node
return node
node.next = insertNodeAtPosition(node.next, data, position - 1)
return node
def insert(self, data, position):
counter = 1
current = self.head
if position > 1:
while current and counter < position:
if counter == position - 1:
data.next = current.next
current.next = data
current = current.next
counter += 1
elif position == 1:
data.next = self.head
self.head = new_element

Categories

Resources