def delete_node(head, value):
p=head
if p is None:
return None
while p.value!=value:
p=p.next
if p.next is head and p.value!=value:
return head
p.value=p.next.value
if p.next==head:
head=p
p.next=p.next.next
return head
The above is my code for deleting a node in a circular linked list based on value of the node!
The code doesn't gimme result for this case-- I've only 1 element in the list and i deleted it.. So the resultant should be an empty set.. But because i took p.value=p.next.value it points back again to itself and the same value is in the list! Can anyone help me out! Thanx in advance! :)
The easiest solution here is to have a dummy node that points to itself in case of an empty list. As a consequence in an empty list we have one node that points to itself (the dummy), in a list with one element the dummy points to the element and the element points to the dummy.
Avoids the need for any special cases and generally simplifies the code. To check if the list is empty you can then just do dummy.next is dummy, also nice.
enter link description here
class node:
def __init__(self, data):
self.data = data
self.next = None
class circularLinkedList:
def __init__(self):
self.head = None
self.tail = None
def insertNode(self, data):
newnode = node(data)
if self.tail is None:
self.head = self.tail = newnode
else:
newnode.next = self.head
self.tail.next = newnode
self.tail = self.tail.next
def printCLL(self):
head = self.head
tail = self.tail
while head.next is not None and head.next is not tail:
print(head.data, end="---")
head = head.next
print(head.data, end="---")
print(tail.data)
c = circularLinkedList()
c.insertNode(1)
c.insertNode(1)
c.insertNode(3)
c.insertNode(4)
c.insertNode(5)
c.printCLL()
Related
Code written in python:
prepend Function is supposed to add a value to the start of the Linked List
display Function is supposed to display the linked list in a List format in python
fromarr Function is supposed to add new nodes to the linked list
class Node:
def __init__(self,value=None):
self.value = value
self.next = None
class SinglyLL:
def __init__(self):
self.head = Node()
self.tail = Node()
def prepend(self,value):
newnode = Node(value)
newnode.next = self.head
self.head = newnode
def append(self,data):
newnode = Node(data)
if self.head is None:
self.head = newnode
return
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = newnode
newnode.next = None
def display(self):
lis = []
cur = self.head
while cur.next != None:
cur = cur.next
lis.append(cur.value)
return lis
def fromarr(self,list):
for i in list:
temp = Node(i)
self.append(temp.value)
newsll = SinglyLL()
newsll.fromarr([1,2,3,4,5])
newsll.prepend(10)
print(newsll.display())
Expected output : [10,1,2,3,4,5]
Actual Output: [None,1,2,3,4,5]
well you are initalising your head with a empty node, and displaying values from self.head.next, so instead of setting element at position 0 you need to set element at position 1.
Adding below code for prepend method
class Node:
def __init__(self,value=None):
self.value = value
self.next = None
class SinglyLL:
def __init__(self):
self.head = Node()
self.tail = Node()
def prepend(self,value):
newnode = Node(value)
if self.head is None:
self.head = newnode
else:
tmp = self.head.next
self.head.next = newnode
newnode.next = tmp
def append(self,data):
newnode = Node(data)
if self.head is None:
self.head = newnode
return
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = newnode
newnode.next = None
def display(self):
lis = []
cur = self.head
while cur.next != None:
cur = cur.next
lis.append(cur.value)
return lis
def fromarr(self,list):
for i in list:
temp = Node(i)
self.append(temp.value)
newsll = SinglyLL()
newsll.fromarr([1,2,3,4,5])
newsll.prepend(10)
print(newsll.display())
Your code has a mix of several approaches to organise a linked list data structure, but they are not compatible:
Your constructor creates a dummy node for the head attribute, which could be an approach when you intend to append all data nodes after that dummy node. The display method is in line with that approach as it doesn't include the value of the dummy node in the result. But the prepend nor the append method use that approach as they treat the head node as a data node.
Your constructor creates a dummy node for the tail attribute. This is an approach that might be used for a doubly linked list, but is not useful for a singly linked list, as the process to append a new node at the end of the list cannot take benefit from this reference.
Although the constructor defines a tail attribute none of the other methods make use of it, nor update it when necessary.
Some other remarks:
It is odd that the display method does not display anything. It would be more appropriate to have an __iter__ method instead which would yield the linked list's values.
fromarr is not a very good name for a method that accepts a list.
It is not intuitive that this is an instance method, as its name suggests that it will create a new list from those values, but you actually need to first create a linked list instance yourself, and then call this method. I would suggest to drop this method and extend the constructor with optional arguments which will be used to populate the constructed linked list.
list is a bad name for a parameter as this name is already in use by native Python.
It would be nice if the Node constructor would accept an optional argument for defining the next attribute.
Here is an update of your code that takes those points into account, and which uses the approach where:
A tail attribute is set and used
No dummy nodes are created
class Node:
def __init__(self, value=None, nxt=None):
self.value = value
self.next = nxt
class SinglyLL:
def __init__(self, *values):
# Don't create nodes here
self.head = self.tail = None
# Allow immediate population from arguments
for value in values:
self.append(value)
def prepend(self,value):
self.head = Node(value, self.head)
self.tail = self.tail or self.head
def append(self, data):
if not self.tail:
self.prepend(data)
else:
self.tail.next = self.tail = Node(data)
def __iter__(self):
cur = self.head
while cur:
yield cur.value
cur = cur.next
newsll = SinglyLL(1,2,3,4,5)
newsll.prepend(10)
print(list(newsll)) # [10, 1, 2, 3, 4, 5]
This is a code to add a new node at the beginning of a linked list and then print the elements in the linked list. But when I run the program I get the following error in the last line when I call the ll1.print_LL() function:
AttributeError: 'NoneType' object has no attribute 'data'
And here is my code:
class Node:
def __init__(self, data):
self.data = data
self.ref = None
class LL:
def __init__(self):
self.head = None
def print_LL(self):
if self.head is None:
print("LL is empty")
else:
node = self.head
while self.head is not None:
print(node.data)
node = node.ref
def add_begin(self, data):
new_node = Node(data)
new_node.ref = self.head
self.head = new_node
ll1 = LL()
ll1.add_begin(10)
ll1.add_begin(20)
ll1.print_LL()
I have seen a post about a similar error on StackOverflow, but I'm still confused.
Why am I getting this error in my code and how do I fix it?
Short Answer:
Change while self.head is not None:
to
while node is not None:
Explanation*
The error message tells you something that you might think of. It tells you that at some point you're trying to get ".data" from a None variable, which means your loops at "some point" reach None.
Now, the issue is at this part
def print_LL(self):
if self.head is None:
print("LL is empty")
else:
node = self.head
while self.head is not None:
print(node.data)
node = node.ref
Here, you are assigning node = self.head which is making the pointer point to the first element (the head), and you WANT to make the pointer move forward, which what you're doing when you said: node=node.ref, however, your test condition is not correct, because you're testing against self.head.
Since self.head is never gonna be None, it will keep looping forever, but the node will keep moving forward and return a None error because there are no more nodes.
The answer:
Change the while loop to:
def print_LL(self):
if self.head is None:
print("LL is empty")
else:
node = self.head
while node is not None:
print(node.data)
node = node.ref
While the breaking error has been pointed out in the answer, there is another intricacy worth considering, add_begin() function should be changed to:
def add_begin(self,data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
new_node.ref = self.head
self.head = new_node
.because when the first time you call add_begin() function, there is no value in head and as such the line
new_node.ref = self.head is meaningless as it is assigning None value to None value.
Also it improves code readability.
I am trying to pop elements from the end of a circular linked list in python. All the elements are getting popped successfully, but error arises when only one node is left. When the last remaining node is popped an error occurs.
Is there any problem with the show function?
class Node(object):
def __init__(self, value):
self.value = value
self.next = None
class CircularLinkedList(object):
def __init__(self, tail = None):
self.tail = tail
def append(self, value):
new_node = Node(value)
if self.tail ==None:
self.tail = new_node
self.tail.next = new_node
if self.tail!=None:
new_node.next= self.tail.next
self.tail.next=new_node
self.tail= new_node
#pop function
def pop(self):
if self.tail==None:
print("Sorry no elements .")
else:
if self.tail.next==self.tail:
self.tail=None
return self.tail
else:
temp=self.tail.next
while temp.next!=self.tail:
temp=temp.next
temp.next=self.tail.next
removed = self.tail
self.tail=temp
print("Popped")
return removed
#display function
def show(self):
current = self.tail
while current.next:
current = current.next
print(current.value)
if current == self.tail:
break
circular = CircularLinkedList()
circular.append(5)
circular.append(9)
circular.append(96)
print("Before deleting:")
circular.show()
circular.pop()
circular.pop()
circular.pop()
circular.show()
Image of the output
When you pop the last element you assign None to self.tail, so in show() in
while current.next:
you are trying to call next from None. Add a check
while current and current.next:
I fixed it so your image shows. The problem is not the popping of the last value. You're doing that correctly. The problem is that your show function cannot handle an empty list. You need to check for that.
You need to make a little change to you pop function to understand how many elements got popped.
Like this
def pop(self):
if self.tail==None:
print("Sorry no elements .")
else:
if self.tail.next==self.tail:
self.tail=None
print("popped") #HERE
return self.tail
else:
temp=self.tail.next
while temp.next!=self.tail:
temp=temp.next
temp.next=self.tail.next
removed = self.tail
self.tail=temp
print("Popped")
return removed
This will make things clear for you. And as others said, the reason for your error is in your show method.
You're making self.tail=None for the last element in pop(). And you're trying to access .next for None.
Here:
def show(self):
current = self.tail
while current.next:
Add an if like this to avoid error
def show(self):
current = self.tail
if current.next == None:
print("circular linkedlist is empty")
return None
while current.next:
current = current.next
print(current.value)
if current == self.tail:
break
There are the following issues in your code:
In the pop method None is returned when the only remaining node is removed. But it should return the removed node. This happens here:
self.tail=None
return self.tail # <-- this will always be None!
Change the pop function to this:
def pop(self):
if not self.tail:
print("Sorry no elements.")
else:
removed = self.tail # also when the only remaining node!
if self.tail.next == self.tail:
self.tail = None
else:
temp = self.tail.next
while temp.next != self.tail:
temp = temp.next
temp.next = self.tail.next
self.tail = temp
print("Popped")
return removed
The show method assumes that the list is not empty. For an empty list it will generate an error on this statement:
while current.next:
So deal with the empty list case separately. Also, it is strange to have this while condition, as there is a break inside the loop, that depends on a more useful condition: make that the loop condition. You could write that method as follows:
def show(self):
if not self.tail:
print("(empty)")
return
current = self.tail.next
while current != self.tail:
print(current.value, end=" ")
current = current.next
print(self.tail.value)
Not an error, but the append method is a bit weird in how it inserts the first node: it will execute both the if blocks. It ends up working correctly, but I find that counter-intuitive. It seems better to write this as an if...else structure, so that exactly one block of code gets executed, not two:
def append(self, value):
new_node = Node(value)
if self.tail:
new_node.next = new_node
else:
new_node.next = self.tail.next
self.tail.next = new_node
self.tail = new_node
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
I have been playing around with Python more recently due to its power and syntax. I've decided to make a linked list from https://www.tutorialspoint.com but with my strong background in C and being use to its manual memory allocation as well as having pointers for one the delete middle function is somewhat confusing to me. I know that objects makes references to other objects and variables and that the Python interpreter automatically handles this:
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
class SLinkedList:
def __init__(self):
self.head = None
def printlist(self):
cur = self.head
while cur is not None:
print(cur.data)
cur = cur.next
def insertAtHead(self, newdata):
NewNode = Node(newdata) #create new node
newNode.next = self.head #create its .next to point to the current node
self.head = newNode #set its .next to point the current head
#creates a linked list with 3 elements
def createOneTwoThree(self):
list = SLinkedList()
list.head = Node('Mon')
e2 = Node('Tues')
e3 = Node('Wed')
list.head.next = e2
e2.next = e3
#function to add at the end of a linked list
def insertAtEnd(self, newdata):
newNode = Node(newdata)#create new node
if self.head = newNode:#if empty insert the thing
self.head = newNode
return
laste = self.head
while(last.next):
last = last.next
last.next = newNode
def inBetween(self, middle_node,newdata):
if middle_node is None:
print('Error 0: The mentioned node is absent')
return
newNode = Node(newdata)
newNode.next = middle_node.next
middle_node.next = newNode
def delete(self, removeKey):
headVal = self.head
if(head is not None):
if (head.data == removeKey):
break
prev = head
head = None
while(head is not None):
if head.data == removeKey:
break
prev = head
head = head.next
if (head == None):
return
prev.next = head.next
head = None
#Link Firt node to second node: list1.head.next = n2*******
I just fail to see what's going on here from a memory point of view that justifies it finding the in-between two said values and having them linked together. I am still new to Python and its classes and structures but from an intuitive aspect the inBetween method makes little sense to me though I see it's most underlying logic. Can someone more versed in Python please explain to my WHY this is happening and what exactly is going on with the objects, references and pointers?