I have a problem with syntax in nodes (data Structure) - python

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

Related

Reversed double linked list by python

why can't print reversed this double linked list by python?
always print 6 or None
please can anyone help me fast to pass this task
///////////////////////////////////////////////////////////////////////////
class Node:
def __init__(self, data=None, next=None, prev=None):
self.data = data
self.next = next
self.previous = prev
sample methods==>
def set_data(self, newData):
self.data = newData
def get_data(self):
return self.data
def set_next(self, newNext):
self.next = newNext
def get_next(self):
return self.next
def hasNext(self):
return self.next is not None
def set_previous(self, newprev):
self.previous = newprev
def get_previous(self):
return self.previous
def hasPrevious(self):
return self.previous is not None
class double===>
class DoubleLinkedList:
def __init__(self):
self.head = None
self.tail = None
def addAtStart(self, item):
newNode = Node(item)
if self.head is None:
self.head = self.tail = newNode
else:
newNode.set_next(self.head)
newNode.set_previous(None)
self.head.set_previous(newNode)
self.head = newNode
def size(self):
current = self.head
count = 0
while current is not None:
count += 1
current = current.get_next()
return count
here is the wrong method ==>
try to fix it without more changes
def printReverse(self):
current = self.head
while current:
temp = current.next
current.next = current.previous
current.previous = temp
current = current.previous
temp = self.head
self.head = self.tail
self.tail = temp
print("Nodes of doubly linked list reversed: ")
while current is not None:
print(current.data),
current = current.get_next()
call methods==>
new = DoubleLinkedList()
new.addAtStart(1)
new.addAtStart(2)
new.addAtStart(3)
new.printReverse()
Your printReverse seems to do something else than what its name suggests. I would think that this function would just iterate the list nodes in reversed order and print the values, but it actually reverses the list, and doesn't print the result because of a bug.
The error in your code is that the final loop has a condition that is guaranteed to be false. current is always None when it reaches that loop, so nothing gets printed there. This is easily fixed by initialising current just before the loop with:
current = self.head
That fixes your issue, but it is not nice to have a function that both reverses the list, and prints it. It is better practice to separate these two tasks. The method that reverses the list could be named reverse. Then add another method that allows iteration of the values in the list. This is done by defining __iter__. The caller can then easily print the list with that iterator.
Here is how that looks:
def reverse(self):
current = self.head
while current:
current.previous, current.next = current.next, current.previous
current = current.previous
self.head, self.tail = self.tail, self.head
def __iter__(self):
node = self.head
while node:
yield node.data
node = node.next
def __repr__(self):
return "->".join(map(repr, self))
The main program can then be:
lst = DoubleLinkedList()
lst.addAtStart(1)
lst.addAtStart(2)
lst.addAtStart(3)
print(lst)
lst.reverse()
print(lst)

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)

Remove Leading and Trailing Single Quote when String Formatting in Python

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.

calling a method in another method errors

class Node:
def __init__(self, data):
self.data = data
self.ref = None
class LinkedList:
def __init__(self):
self.head = None
def show(self):
if self.head is None:
print("This linked lists is empty")
else:
currentnode = self.head
while currentnode is not None:
print(currentnode.data, end=" --> ")
currentnode = currentnode.ref
def addelement(self, value):
newnode = Node(value)
newnode.ref = self.head
self.head = newnode
def lenofll(self , i = 0):
while self.head is not None:
i = i +1
self.head = self.head.ref
return i
def middle(self):
i = 0
lent = self.lenofll()
if self.head is None: # self.head changed to None after calling lenofll method.
print("linked list is empty")
I wanted to get the length of linked lists in the middle method. But as I called self.lenofll(), it changed the self.head to None.
What can I do to fix this?
Indeed, doing self.head = self.head.ref modifies the head. You should not make any modifications to self.head in a method whose job is just to search in the list -- without modifying anything to it.
As you can see, that method keeps looping until self.head is not None is not true, i.e. when self.head is None. No wonder that self.head is None after running this method!
Use a local variable for this iteration instead:
def lenofll(self, i = 0):
node = self.head # use local variable
while node is not None:
i += 1
node = node.ref
return i

Deleting the last element in my linked list

I've created a list using only the Node class
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
def __str__(self):
return str(self.data)
I've intialized the list and the last Node is None.
I'm trying to delete this node but don't know how to?
One good way to do this is to keep track of the previous node and the current node, and then when you reach the end of the list, set the next of the previous to None.
prev = None
cur = head
while cur.next is not None:
prev = cur
cur = cur.next
if prev: #in case the head is the tail
prev.next = None
You'll probably want a List class to manage your nodes.
class List:
def __init__(self):
self._nodes = None
def push(self, node):
node.set_next(self._nodes)
self._nodes = node
return self
def pop(self):
if self._nodes is None:
return None
temp = self._nodes
self._nodes = temp.get_next()
return temp
def __len__(self):
l = 0
n = self._nodes
while n is not None:
n = n.get_next()
l += 1
return l
def remove(self, node):
n = self._nodes
p = None
while n is not None:
if n is node:
p.set_next(n.get_next())
n.set_next(None)
return True
p = n
n = n.get_next()
return False
def del_from_end(self):
if self.head is None:
return "No node to delete"
else:
current = self.head
while current.next.next is not None:
current = current.next
current.next = None
Add this method in your linked list class which would look like
class LinkedList():
def __init__(self, head=None):
if head == "" or head is None:
self.head = None
else:
self.head = Node(head)

Categories