I'm trying to learn python so I decided to implement a Singly Linked List but I stumbled upon a weird problem.
As you could see from the screenshot above, the output when I'm trying to search for the index of a node has a leading and trailing single quote.
class Node:
next_node = None
def __init__(self, data):
self.data = data
def __repr__(self):
return "<Node data: %s>" % self.data
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def is_empty(self):
return self.head == None
def size(self):
current = self.head
count = 0
while current:
count += 1
current = current.next_node
return count
def append(self, data):
new_node = Node(data)
if self.is_empty():
self.head = new_node
else:
self.tail.next_node = new_node
self.tail = new_node
def search_node(self, key):
current = self.head
position = 0
while current:
if current.data == key:
# This returns with a leading and trailing single quote
return "<Node index: %s>" % position
else:
current = current.next_node
position += 1
return None
def search_index(self, index):
if index == 0:
return self.head
elif index == self.size() - 1:
return self.tail
else:
current = self.head
position = 0
while position < index:
current = current.next_node
position += 1
return current
def __repr__(self):
nodes = []
current = self.head
if self.is_empty():
return "<Empty>"
if self.size() == 1:
return "<Head: Tail: %s>" % current.data
while current:
if current is self.head:
nodes.append("<Head: %s>" % current.data)
elif current.next_node is None:
nodes.append("<Tail: %s>" % current.data)
else:
nodes.append("<%s>" % current.data)
current = current.next_node
return "-> ".join(nodes)
What's causing this behavior? I saw some articles about the repr function causing it but I'm not really sure.
I made some notes in your code that will hopefully help with identifying why your outputs are not consistent.
class LinkedList:
def __init__(self):
self.head = None < - node or None
self.tail = None < - node or None
def search_node(self, key): # <- function return will be str or None
current = self.head
position = 0
while current:
if current.data == key:
return "<Node index: %s>" % position # <-- Returning a string
else:
current = current.next_node
position += 1
return None # <--- Returning None
def search_index(self, index): # <- function returns node or None
if index == 0:
return self.head # <- returing node or None
elif index == self.size() - 1:
return self.tail # <- returning node or None
else:
current = self.head
position = 0
while position < index:
current = current.next_node
position += 1
return current # <- returning node or None
The __repr__(str) of a string will always have the quotes surrounding it.
Related
This code should create a node but I have a problem with it I tried to fix it but I couldn`t
I want to know why there is a problem at in the Linked_List (Next_Node)
that is what show in the error "(Cannot assign member "next_node" for type "node"
Expression of type "node | None" cannot be assigned to member "next_node" of class "node"
Type "node | None" cannot be assigned to type "None"
Type cannot be assigned to type "None")"
class node :
data = None
next_node = None
def __init__(self , data) :
self.data = data
def __repr__(self) :
return "<node data: %s>" % self.data
class linked_list :
def __init__(self ):
self.head = None
def add (self , data):
new_node = node(data)
new_node.next_node = self.head
self.head = new_node
def __repr__ (self):
nodes =[]
current = self.head
while current :
if current is self.head:
nodes.append ("[:head %s ]" % current.data)
elif current.next.node is None :
nodes.append ("[tail: %s ]" % current.data)
else :
nodes.append ("[:%s ]" % current.data)
current = current.next_node
return "->".join(nodes)
There are several problems with current attempt:
The Node class as pointed by John Gordon is wrongly constructed. The data and next_node should be in __init__ method.
The add method is not adding new node in correct position.
The __repr__ is not looping through all the nodes in the linked list because of wrong indentation.
Updated code:
class node:
def __init__(self, data):
self.data = data
self.next_node = None
def __repr__(self):
return "<node data: %s>" % self.data
class linked_list:
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
def size(self):
current = self.head
count = 0
while current:
count += 1
current = current.next_node
return count
def add(self, data):
new_node = node(data)
if self.head == None:
self.head = new_node
else:
current = self.head
while current.next_node != None:
current = current.next_node
current.next_node = new_node
def __repr__(self):
nodes = []
current = self.head
while current:
if current is self.head:
nodes.append("[:head %s ]" % current.data)
elif current.next_node is None:
nodes.append("[tail: %s ]" % current.data)
else:
nodes.append("[:%s ]" % current.data)
current = current.next_node
return "->".join(nodes)
l = linked_list()
l.add(1)
l.add(2)
l.add(3)
print(l)
Output:
[:head 1 ]->[:2 ]->[tail: 3 ]
class node :
data = None
next_node = None
def __init__(self , data):
self.data = data
I think the problem is because of the node class definition.
The way you've defined the next_node variable, it is a direct attribute of the class, so it is shared among all instances of the class.
I think you intended that attribute to be inside the __init__ method, so that each instance would have its own separate copy of that variable:
class node :
def __init__(self , data) :
self.data = data
self.next_node = None
I'm trying to learn how to create linked lists. This is my first time doing this and the reason of code failure may be something basic I'm missing.
That being said, I am unable to figure out even after using vs code's debugger. It simply stops at the end of the append method when it is called the second time.
I am using recursion to traverse to the tail. Could that be a the problem?
class Node:
def __init__(self, data, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self):
self.head = None
def __repr__(self):
if not self.head:
return 'Linked list is empty'
linked_list = self.head.data
if self.head.next == None:
return linked_list
current = self.head
while current.next != None:
linked_list += '\n|\nV' + current.data
return linked_list
def append(self, value):
if not self.head:
self.head = Node(data=value)
return
tail = self.tail()
tail.next = Node(data=value)
def tail(self):
tail = self._traverse_to_tail(self.head)
while tail.next != None:
tail = self._traverse_to_tail(tail)
return tail
def _traverse_to_tail(self, current_node, recursion_count=0):
print(current_node.data)
if recursion_count > 997:
return current_node
if current_node.next == None:
return current_node
current_node = current_node.next
recursion_count += 1
return self._traverse_to_tail(current_node, recursion_count)
if __name__ == '__main__':
ll = LinkedList()
ll.append('foo')
ll.append('baz')
print(ll)
The problem is you have an infinite loop in the __repr__() function, because you never increment current.
def __repr__(self):
if not self.head:
return 'Linked list is empty'
linked_list = self.head.data
if self.head.next == None:
return linked_list
current = self.head
while current.next != None:
current = current.next
linked_list += '\n|\nV' + current.data
return linked_list
I am still a beginner in programming. I learned the basics in Python. Right now I'm learning data structures and algorithms.
I have implemented a linked list. But there is a problem inside it. My size is 0 after removing one element. I do not know where the error comes from.
This code was tested in Python 3.7.4.
class Node(object):
def __init__(self, data):
self.data = data
self.nextNode = None
class LinkedList(object):
def __init__(self):
self.head = None
self.size = 0
# O(1)
def insertStart(self, data): # insert data at beginnning of the list
self.size += 1
newNode = Node(data)
if not self.head: # the head is None
self.head = newNode
else: # the head is not None
newNode.nextNode = self.head
self.head = newNode
def remove(self,data):
if self.head is None:
return
self.size-=self.size
currentNode=self.head
previousNode=None
while currentNode.data != data:
previousNode=currentNode
currentNode=currentNode.nextNode
if previousNode is None:
self.head = currentNode.nextNode
else:
previousNode.nextNode=currentNode.nextNode
# O(1)
def size1(self):
return self.size
# O(N)
def size2(self):
actualNode = self.head
size = 0
while actualNode is not None:
size += 1
actualNode = actualNode.nextNode
return size
# O(N)
def insertEnd(self, data):
self.size += 1
newNode = Node(data)
actualNode = self.head
while actualNode.nextNode is not None:
actualNode = actualNode.nextNode
actualNode.nextNode = newNode
def traverseList(self):
actualNode = self.head
while actualNode is not None:
print("%d " % actualNode.data)
actualNode = actualNode.nextNode
a=LinkedList()
a.insertStart(3)
a.insertStart(4)
a.insertEnd(5)
#a.remove(3)
#a.remove(4)
a.remove(5)
print(a.traverseList())
print(a.size1())
You're subtracting self.size from self.size, which will obviously return 0. You just want to remove 1 (self.size -= 1)
Also, you have another bug. What happens if you try to remove a node which doesn't exist? Your condition while currentNode.data != data: will raise a NoneType error, because it will eventually reach the end of the list (None) without having found the node.
I am learning python and data structure. I was implementing singly linked list methods which included inserting at head and at given position. I ended up writing this code :
class Node :
def __init__(self,data=None,next_node=None) :
self.data = data
self.next = next_node
class LinkedList :
def __init__(self) :
self.head = None
def insertathead(self,new_data) :
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def InsertNpos(self,new_data,pos):
start = self.head
if pos == 0:
return Node(new_data, self.head)
while pos > 1:
self.head = self.head.next
pos -= 1
self.head.next = Node(new_data, self.head.next)
return start
def PrintLinkList(self) :
temp = self.head
while (temp) :
print (temp.data)
temp = temp.next
if __name__ == '__main__' :
llist = LinkedList()
llist.insertathead(8)
llist.insertathead(3)
llist.insertathead(10)
llist.insertathead(12)
llist.insertathead(15)
llist.insertathead(2)
llist.InsertNpos(1,2)
llist.PrintLinkList()
Output:
15
1
12
10
3
8
Now, just inserting at head works fine but InsertNpos(1,2) gives wrong output. The output is supposed to be 2,15,1,12,10,3,8.Please tell me where my code is wrong.
When you insert at position pos, your insertion routine deletes the first pos-1 elements of the list. It changes the head pointer on each iteration. You need a local variable to iterate through the list. Also, why are you returning a value? You never use it. The only purpose of this method is to update the list in place.
def InsertNpos(self,new_data,pos):
if pos == 0:
self.head = Node(new_data, self.head)
return
start = self.head
while pos > 1:
start = start.next
pos -= 1
start.next = Node(new_data, start.next)
New output:
Before insertion
2
15
12
10
3
8
After insertion
2
15
1
12
10
3
8
Even though the answer has already been accepted, I tried the solution and as AChampion suggested it didn't work for me for inserting at 0, but my solution did:
class Node :
def __init__(self,data=None,next_node=None) :
self.data = data
self.next = next_node
class LinkedList :
def __init__(self) :
self.head = None
def insertathead(self,new_data) :
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def InsertNpos(self,new_data,pos):
if pos == 0:
self.head = Node(new_data, self.head)
return self.head
i = 0
curr = self.head
while curr.next:
if i == pos - 1:
curr.next = Node(new_data, curr.next)
return self.head
curr = curr.next
i += 1
curr.next = Node(new_data)
return self.head
def PrintLinkList(self) :
temp = self.head
while (temp) :
print (temp.data)
temp = temp.next
This will insert the item at the end if pos is out of range.
def insertNodeAtPosition(head, data, position):
current = head
if not head:
head = SinglyLinkedListNode(data)
return head
# Shift to element before position i.e. before_node
# Change it to point to new_node
# Set new_node.next to before_node.next
for _ in range(position-1):
current = current.next
temp = current.next
new_node = SinglyLinkedListNode(data)
current.next = new_node
new_node.next = temp
return head
I'm writing code for a Linked List in Python and here's part of the code:
class LinkedList:
def __init__(self):
self.head = None
def search(self, n, value):
if n is None:
return False
elif n.data == value:
return True
else:
return search(n.next, value)
def append(self, new_value):
if self.head is None:
self.head = LinkedListNode(new_value)
else:
node = self.head
while node.next != None:
node = node.next
node.next = LinkedListNode(new_value)
def remove(self, position):
if position > 0:
node = self.head
l = 0
while node != position - 1:
l += 1
node = node.next
node.next = node.next.next
elif position == 0:
self.head = self.head.next
I'm just wondering how to implement the search() method? I think I have the right idea, but it's not working. Thank you!
When you call the method inside the same class, you need to qualify it with self.
def search(self, n, value):
if n is None:
return False
elif n.data == value:
return True
else:
return self.search(n.next, value) # <--
BTW, current search implementation requires user to pass n (LinkedList.head maybe). So I would make a wrapper to search from head, so user doesn't need to specify linked_list_instance.head every time:
def search_from_head(self, value):
return self.search(self.head, value)