python single linked list does not work properly - python

the add method() only prints just two value, I want to print all the number what I added. size does work well but I do not know why value does not work when i want to print all the value
enter code here
class Node():
def __init__(self,value):
self.next =None
self.val =value
class single_linked_list():
def __init__(self):
self.head =None
self.size =0
def add(self,val):
node =Node(val)
if self.head is None:
self.head =node
self.size +=1
else:
self.head.next =node
self.size +=1
def __str__(self):
vals =[]
node =self.head
while node is not None:
vals.append(node.val)
node =node.next
return f"[{','.join(str(val)for val in vals)}]"
sl=single_linked_list()
sl.add(3)
sl.add(5)
sl.add(50)
sl.add(9)
print(sl)
print(sl.size)
# it just show these value :[3,9]
#4 as size fine

Problem
The problem is that you are covering only 2 cases in the add() method:
There are ZERO nodes in the list.
There is only ONE node in the list
What about the case when there is more than 1 node in the list?
Let's assume there are two nodes in the list: 1 -> 2
Now, to add 3 in the list, the add() method will check if the head is None. Which is not the case because there are 2 elements.
Then, it will simply add 3 as the next of head. Which was actually set to 2 before. Therefore, 2 is lost and the new list is 1 -> 3
Solution
To solve this issue, you have to edit the add() function and check if there is more than 1 node in your list. It can be done like this:
def add(self,val):
node = Node(val)
if self.head is None:
self.head = node
self.size += 1
else:
curr_node = self.head
# Go to the last element of the list
while curr_node.next:
curr_node = curr_node.next
# Add new element after the last element
curr_node.next = node
self.size += 1

That is because your add method is not really adding nodes to the list, it is just replacing the head.next value. So you have at most 2 nodes in the list with new values just replacing the second position.
Here's the fixed code for add method:
def add(self,val):
node =Node(val)
if self.head is None:
self.head =node
self.size +=1
else:
currentNode = self.head
while currentNode.next:
currentNode = currentNode.next
currentNode.next = node
self.size += 1
Here's a Repl.it link, if you want to see the output - https://repl.it/repls/RewardingVengefulTask

class Node():
def __init__(self,value):
self.next =None
self.val =value
class single_linked_list():
def __init__(self):
self.head =None
self.size =0
def add(self,val):
node =Node(val)
if self.head is None:
self.head =node
self.size +=1
else:
self.head.next =node
self.size +=1

Related

Why does the latest "append" in my python doubly linked list have no effect?

This is part of my doubly linked list deque python code.
The 'appendleft' function written almost similar to the 'append' function is normally output. Why is the last 'append('apple')' code not output normally in the 'Group_of_append' function?
class Node:
def __init__(self,item,prev,next):
self.item = item
self.prev = prev
self.next = next
class deque:
def __init__(self,name):
self.name = name
self.head = Node(None,None,None)
self.tail = Node(None,self.head,None)
self.head.next = self.tail
self.size = 0
def append(self,item):
current = self.head
new_node = Node(item,None,None)
while current.next != None:
current = current.next
current.next = new_node
new_node.prev = current
self.tail = new_node
self.size += 1
return
def appendleft(self,item):
current = self.tail
new_node = Node(item,None,None)
while current.prev != None:
current = current.prev
current.prev = new_node
new_node.next = current
self.head = new_node
self.size += 1
return
def print_list(self):
p = self.head
while p.next != None:
if p.item == None:
pass
else:
print(p.item,end=' ')
p = p.next
def Group_of_append(self):
print('Group_of_append')
self.append('graphe')
self.append('cherry')
self.append('apple')
self.appendleft('watermelon')
self.appendleft('strawberry')
self.print_list()
print(" ")
deq = deque('name')
deq.Group_of_append()
the result is
strawberry watermelon graphe cherry
The last append code on Group_of_append, self.append('apple') have no effect.
While defining the 'append' function, I thought that there would be no output due to one more size being insufficient.
So, I changed 'append' function on deque like this
def append(self,item):
self.size += 1
current = self.head
new_node = Node(item,None,None)
while current.next != None:
current = current.next
current.next = new_node
new_node.prev = current
self.tail = new_node
self.size += 1
return
But the result was same(still the lastest 'append' function doesn't print anything)
strawberry watermelon graphe cherry
Your appends work fine. Problem lies in your print_list function which stops when p.next is None. Which means your last element will not be printed because its next is None.
All in all, your logic for this list is very strange and could use a lot of rework, it would make finding mistakes like this one a lot easier for you. For example, this iterating through the whole list when appending even though you have both head and tail readily available in the deque object.

TypeError: DoubleLinkedList.add() takes 1 positional argument but 2 were given

I am getting this error. I go through this concept but could not find the error. I am making a link list but when giving values it's showing me this error TypeError: DoubleLinkedList.add() takes 1 positional argument but 2 were givenI got through the below concept but I could not find the error or what to do. I am new in python programming
class Node:
def __init__(self, value):
self.next = None
self.prev = None
self.val = value
class DoubleLinkedList:
def __init__(self, ):
self.head = None
self.tail = None
self.size = 0
def add(self):
node = Node()
if self.tail is None:
self.head = node
self.tail = node
self.size += 1
else:
self.tail.next = node
node.prev = self.head
self.tail = node
self.size += 1
def __str__(self):
vals = []
node = self.head
while node is not Node:
vals.append(node.val)
node = node.next
return f"[{','.join((str(val) for val in vals))}]"
my_list = DoubleLinkedList()
my_list.add(1)
my_list.add(5)
my_list.add(2)
print(my_list)
```
The reason why you see this error is because you only let add(self) to have one positional argument, which is self. What you want is something like follows:
def add(self, value):
node = Node(value)
if self.tail is None:
self.head = node
self.tail = node
self.size += 1
else:
self.tail.next = node
node.prev = self.head
self.tail = node
self.size += 1
Note that this answer doesn't look for your logic, only to fix your problem regarding positional arguments.
Also, self is a special keyword in Python used for instance variables and methods. When you create a new instance of Node as node = Node(), you automatically pass self argument, and the same goes for add method.
When you call my_list.add(1), Python inherently understands it as
my_list.add(self,1)
Of course, here self is equal to my_list. That's why Python tells you "I already got self, however, you've passed another value, so I will throw an error.
You have to modify your add function like this
def add(self, value):
node = Node(value)
if self.tail is None:
self.head = node
self.tail = node
self.size += 1
else:
self.tail.next = node
node.prev = self.head
self.tail = node
self.size += 1
And you should modify a little also the __str__ function
def __str__(self):
vals = []
node = self.head
while node is not None:
vals.append(node.val)
node = node.next
return ','.join((str(val) for val in vals))

Complete Class Python

I am doing an assignment and it is not going very well. It is my code which is not working super good:
from dataclasses import dataclass
#dataclass
class Node:
value: int = None
nxt: Node = None
#dataclass
class Deque:
head: Node = None # First node in queue
tail: Node = None # Last node in queue
size: int = 0
def add_first(self, n):
new = Node(n, None)
if self.head is None:
self.head = new
self.tail = new
self.size += 1
s = "{ "
node = self.head
while node is not None:
s += str(node.value) + " "
node = node.nxt
s += "}"
return s
def add_last(self, n):
new = Node(n, None)
if self.head is None:
self.head = new
self.tail = new
else:
self.tail.nxt = new
self.tail = new
self.size += 1
def get_last(self):
if self.tail is None:
print("Get can't be applied on an empty list")
return None
else:
return self.tail.value
def get_first(self):
if self.head is None:
print("Get can't be applied on an empty list")
return None
else:
#node = self.head
return self.head.value
def remove_first(self):
if self.head is None:
print("Remove can't be applied on an empty list")
elif self.head == self.tail:
s = self.head.value
self.head = None
self.tail = None
self.size -= 1
return s
elif self.size == 1:
node = self.head
self.head = self.head.nxt
self.size -= 1
return node.value
Output:
{ 1 2 3 4 5 6 7 8 9 10 }
Size: 10
{ 20 19 18 17 16 15 14 13 12 11 1 2 3 4 5 6 7 8 9 10 }
Size: 20
Update:
I found an answer to my question. It was issues regarding def add_first and def remove last as well as def remove first.
Because this is homework I'm not going to give away the fixed code, but I will point out what needs fixing. I believe I figured out all the required fixes, but I could be wrong since you didn't share the code used to test your Deque:
Your add_first method is unnecessarily stepping through all the
Nodes, then setting the last Node (the tail)'s nxt value to the
new Node, meaning the new Node will appear at the end of the Deque.
Instead, all you need to do is set the nxt of the new Node to the
current head, and set head to the new Node.
Your remove_first doesn't account for any case except if there's
one Node in the Deque. You have to set the Deque's head to its old
head's nxt Node in all other cases.
Your remove_last also doesn't account for any case except if
there's one Node in the Deque. In all other cases, you have to loop
through the Deque's Nodes, starting with head, until you find a
Node whose nxt value is the Deque's tail, then set its nxt to
None, and set the Deque's tail to that Node.
Example of finding the Node before the tail Node:
node = self.head
while node.nxt != self.tail:
node = node.nxt
node.nxt = None
self.tail = node

Create a tester class in a linked list for showing even numbers

This is my node class and Mylist class
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class MyList():
def __init__(self,head=None):
self.head = head
def showList(self):
temp = self.head
while (temp):
print(temp.data)
temp = temp.next
if self.head is None:
print("Empty List")
This is my showeven number function
def showeven(even):
head = None
while even:
if even.data % 2 == 0:
new_Node = Node(even.data, None)
if head is None:
tail = new_Node
head = new_Node
else:
tail.next = new_Node
tail = new_Node
MyList(head).showList()
Can you guys help me create a tester class or some sort of thing for this
You can simply write something like this.
def print_even_nodes(self):
traverse = self.head
while (traverse != None):
if (traverse.data % 2 == 0):
print(traverse.data)
traverse = traverse.next
It is pretty much similar to printing the whole singly linked list, the only key difference is that we check if that particular node (node.data field) is divisible by 2. If it is true we print out the element else we go to the next node.

Error when deleting a node in a Linked List <ListNode.ListNode object at 0x0000000267320>

I am making a linkedlist, and I had to add in some different functions such as max, min , count and index for my list. I now have to add a remove function which is this snippet of code.
def removeItem(self, position):
''' removeItem removes a selected, because python has a built in "garbage remover",
you don't have to physically delete the node, you only have to skip that node link and python will destroy it
by it self.'''
currentNode = self.head
previousNode = None
count = 0
while count != position:
#This is a quick check to make sure the next node isn't empty.
if currentNode.link is None:
print("Position Invalid")
return None
previousNode = currentNode
currentNode = currentNode.link
count += 1
#Node.Link should link to the next node in the sequence.
previousNode.link = currentNode.link
return currentNode
I am basically just trying to link over the next node in the sequence, so that the built-in garbage remover will remove that node from the sequence. However, I am getting the following error message, which I know has to do something with my instance.
C:\Python33\python.exe "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter4/Test.py"
900
1
1
2
<ListNode.ListNode object at 0x0000000002679320>
Process finished with exit code 0
Why is it printing out this weird ListNode.ListNode object at the end?
Here is my testing code:
from ListNode import ListNode
from LinkedList import LinkedList
node1 = ListNode(1)
node2 = ListNode(900)
node3 = ListNode(3)
node4 = ListNode(99)
node1.link = node2
node2.link = node3
node3.link = node4
linked_list = LinkedList((1, 900, 3, 99))
print(linked_list.__max__())
print(linked_list.__min__())
print(linked_list.getCount(900))
print(linked_list.getIndex(3))
print(linked_list.removeItem(3))
This is my code for my ListNode class:
# ListNode.py
class ListNode(object):
def __init__(self, item = None, link = None):
'''creates a ListNode with the specified data value and link
post: creates a ListNode with the specified data value and link'''
self.item = item
self.link = link
This is my code for my LinkedList class:
from ListNode import ListNode
class LinkedList(object):
#--------------------------------------------------------------
def __init__(self, seq=()):
""" Pre: Creates a Linked List
Post: Creates a list containing the items in the seq=()"""
if seq == ():
# If there is no items to be put into the list, then it creates an empty one.
self.head = None
else:
# Creates a node for the first item.
self.head = ListNode(seq[0], None)
# If there are remaining items, then they're added while keeping track of the last node.
last = self.head
for item in seq[1:]:
last.link = ListNode(item, None)
last = last.link
self.size = len(seq)
#-------------------------------------------------------------
def __len__(self):
'''Pre: Nothing.
Post: Returns the number of items in the list.'''
return self.size
#-------------------------------------------------------------
def __max__(self):
''' Goes through each node and compares what the max is for the linked list.
Post: Finds the max of the linked list and returns that value.'''
if self.head is None:
return None
max_value = self.head.item
node = self.head.link
while node is not None:
if node.item > max_value:
max_value = node.item
node = node.link
return max_value
#--------------------------------------------------------------
def __min__(self):
''' Goes through each node and compares what the min is for the linked list.
Post: Finds the min of the linked list and returns that value.'''
if self.head is None:
return None
min_value = self.head.item
node = self.head.link
while node is not None:
if node.item < min_value:
min_value = node.item
node = node.link
return min_value
#--------------------------------------------------------------
def getCount(self, yourData):
''' This function counts the amount of times a certain item is in the Linked List.'''
count = 0
node = self.head
for i in range(self.size):
data = node.item
if data is yourData:
count += 1
node = node.link
return count
#--------------------------------------------------------------
def getIndex(self, yourData):
''' getIndex finds the index of the selected item and returns that value. '''
node = self.head
if node is None:
return None
for i in range(self.size):
data = node.item
if data == yourData:
return i
node = node.link
raise IndexError
#--------------------------------------------------------------
def removeItem(self, position):
''' removeItem removes a selected, because python has a built in "garbage remover",
you don't have to physically delete the node, you only have to skip that node link and python will destroy it
by it self.'''
currentNode = self.head
previousNode = None
count = 0
while count != position:
#This is a quick check to make sure the next node isn't empty.
if currentNode.link == None:
print("Position Invalid")
return None
previousNode = currentNode
currentNode = currentNode.link
count += 1
#Node.Link should link to the next node in the sequence.
previousNode.link = currentNode.link
return currentNode
#--------------------------------------------------------------
If anyone could help me out to find out why my removeItem function isn't working that would be helpful!
On a side note, I'm also trying to make a doubly linked list of this list, I know I need to add a prev_node function into my ListNode function, but what else do I need to add? Thanks again!
If your method is returning a <LinkNode object at 0xmemoryaddr> string then it is working fine. You are printing the removed node, and Python is using the default repr() representation for that instance.
If you wanted to make it more readable, you could give the ListNode a object.__repr__ method:
def __repr__(self):
next = 'None' if not self.link else '...' # just to indicate
return 'ListNode({!r}, {})'.format(self.item, next)
This then will print ListNode(99, None) instead of the <ListNode object at 0xmemoryaddr> string Python defaulted to:
>>> ll = LinkedList((1, 900, 3, 99))
>>> ll.head
ListNode(1, ...)
>>> ll.head.link
ListNode(900, ...)
>>> ll.head.link.link
ListNode(3, ...)
>>> ll.head.link.link.link
ListNode(99, None)
One thing you do have to take into account: you need to adjust the length of the list too; on successful removal, subtract 1 from self.size.

Categories

Resources