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.
Related
when deleting the entire linked list using the "delete_entire(self)" method. It throws no attribute error. Although the above code is running fine. Instead of printing the blank list, it is giving the no attribute error.
class Node:
def __init__(self,value):
self.value = value
self.next = None
class CircularSinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def __iter__(self):
node = self.head
while True:
yield node
if node.next is self.head:
break
node = node.next
def insertion(self, value, location):
new_node = Node(value)
if self.head is None:
self.head = new_node
self.tail = new_node
self.tail.next = self.head
else:
if location == 0:
new_node.next = self.head
self.head = new_node
self.tail.next = new_node
elif location == -1:
self.tail.next = new_node
new_node.next = self.head
self.tail = new_node
else:
temp_node = self.head
index = 0
while index < location -1:
if temp_node.next is 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 new_node.next is self.head:
self.tail = new_node
#---------------------------------------------------------------------------------------------#
# deleting the entire linked list
def delete_entire(self):
self.head = None
self.tail.next = None
self.tail = None
cll = CircularSinglyLinkedList()
cll.insertion(2,1)
cll.insertion(3,2)
cll.insertion(5,3)
cll.insertion(6,4)
cll.insertion(0,0)
cll.insertion(10,-1)
print([node.value for node in call])
output = [0, 2, 3, 5, 6, 10]
cll.delete_entire()
print([node.value for node in call])
AttributeError: 'NoneType' object has no attribute 'value'
The expected output is to be
[ ]
Your __iter__() method always yields once, even when the list is empty, since it does yield node before checking whether node is None. Whenthe list is empty, that will yield None, and the caller will try to use None.value.
You should stop the loop as soon as node is None.
def __iter__(self):
node = self.head
while node:
yield node
node = node.next
I am trying to write a program to insert a node at a specific position and the errors I am getting are,
AttributeError: 'NoneType' object has no attribute 'next'
and also
Function missing 2 required positional arguments: 'x' and 'y'
Code:
class SinglyLinkedListNode:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def insertnode_end(self, data):
node = SinglyLinkedListNode(data)
if not self.head:
self.head = node
else:
self.tail.next = node
self.tail = node
def print_ll(self):
temp = self.head
while temp is not None:
print(temp.data, end=" ")
temp = temp.next
def insertNode_pos(self, data, pos):
new_node = SinglyLinkedListNode(data)
if (pos == 0):
new_node.next = self.head
self.head = new_node
temp = self.head
while temp.next is not None:
for _ in range(pos - 1):
temp = temp.next
new_node.next = temp.next
temp.next = new_node
llist_count = int(input())
llist = SinglyLinkedList()
for _ in range(llist_count):
llist_item = int(input())
llist.insertnode_end(llist_item)
data = int(input())
pos = int(input())
llist.insertNode_pos(data, pos)
llist.print_ll()
I don't see x and y in your code. It is helpful if you include the full traceback. It seems that your function is hitting the last node in the list, whose next item is None. Obviously, None doesn't have the next and data attributes.
Meanwhile, I modified your insertNode_pos function. One important line here is return if pos == 0. Your function doesn't need to continue in that case.
def insertNode_pos(self, data, pos):
new_node = SinglyLinkedListNode(data)
if pos == 0:
new_node.next = self.head
self.head = new_node
return
temp = self.head
for iter in range(pos):
if iter == 0:
temp = self.head
else:
temp = temp.next
new_node.next = temp.next
temp.next = new_node
One more note is that implementing __str__ is a more common practice for printing content of your data:
def __str__(self):
output = []
temp = self.head
while temp is not None:
output.append(str(temp.data))
temp = temp.next
return ",".join(output)
Then you can simply say print(llist)
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
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()
This is my code ignore if any of the spacing is wrong the code works perfectly fine in python.
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return "Node({})".format(self.value)
def getNext(self):
return self.next
def getValue(self):
return self.value
def setNext(self, new_next):
self.next = new_next
def setValue(self, new_value):
self.value = new_value
__repr__ = __str__
class OrderedLinkedList:
def __init__(self):
self.head=None
self.tail=None
self.count = 0
def __str__(self):
temp=self.head
out=[]
while temp:
out.append(str(temp.value))
temp=temp.next
out=' '.join(out)
return ('Head:{}\nTail:{}\nList:{}'.format(self.head,self.tail,out))
__repr__=__str__
def add(self, value):
#write your code here
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
self.head.setNext(self.tail)
if self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
self.count += 1
def pop(self):
#write your code here
if self.head == None:
return 'List is empty'
if len(self) == 1:
value = self.head.getValue()
self.head = None
self.tail = None
self.count = 0
return value
current = self.head
while current.next is not self.tail:
current = current.getNext()
value = self.tail.getValue()
self.tail = current
self.tail.next = None
self.count -= 1
return value
def isEmpty(self):
#write your code here
return self.head == None
def __len__(self):
#write your code here
return self.count
The only problem I have with it is that when I first use the function add it adds the number twice. Below is the outcome when I first call add every time after that it adds the number only once. How can I fix it so it only adds the first number once instead of twice.
>>> x=OrderedLinkedList()
>>> x.add(2)
>>> print(x)
Head:Node(2)
Tail:Node(2)
List:2 2
add(item) adds a new Node with value=item to the list making sure that the ascending order is preserved. It needs the item and returns nothing.
Yep, it adds the first number twice since you need fix a bug in your add method by adding an elif:
def add(self, value):
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
# self.head.setNext(self.tail) ## remove to prevent infinity loop
elif self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
Since, if the head es None once the data is added then the next conditional always will execute one of the two parts on if or else.