Complete Class Python - 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

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))

Delete last node in linked list

I am implementing deletion of last node in linked list using Python. Below is my code:
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
# Iterating till the last Node
while temp.next != None:
temp = temp.next
temp = None
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)
However, in output I'm still getting the complete linked list.
10 20 30
How is it printing 30 when the last node is already set to temp = None?
Well, your linked list is:
10 -> 20 -> 30
^head
Your iteration:
10 -> 20 -> 30
^head ^temp
Then when you do temp = None, just means(you just assign None to temp):
10 -> 20 -> 30 None
^head ^temp
A correct way is when you iterate on 20, do temp.next = None to remove the reference to the last node. So your code might be:
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
# Iterating till the last Node
while temp.next.next != None:
temp = temp.next
temp.next = None
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)
This code would work when your linked list contain at least two elements. When there is only one element, this will raise exception. I would recommend you use a dummy head node which next point to the real head node.
#Another way of solving
class Node:
def __init__(self, key):
self.key = key
self.next = None
def printList(head):
curr = head
while curr != None:
print(curr.key, end=" ")
curr = curr.next
def deleteLastNode(head):
if head == None:
return None
temp = head
prev=None #creating the value of previous element
# Iterating till the last Node
while temp.next != None:
prev=temp #updating for every iteration
temp = temp.next
prev.next = None #returning as NONE value
return head
# Driver code
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
head = deleteLastNode(head)
printList(head)

python single linked list does not work properly

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

Linked List in Python- Append, Index, Insert, and Pop functions. Not sure with code/errors

This assignment asks us to implement the append, insert, index and pop methods for an unordered linked-list.
(What I have so far)
def main():
class Node:
def __init__(self, data):
self.data = data
self.next_node = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def AppendNode(self, data):
new_node = Node(data)
if self.head == None:
self.head = new_node
if self.tail != None:
self.tail.next = new_node
self.tail = new_node
def PrintList( self ):
node = self.head
while node != None:
print (node.data)
node = node.next
def PopNode( self, index ):
prev = None
node = self.head
i = 0
while ( node != None ) and ( i < index ):
prev = node
node = node.next
i += 1
if prev == None:
self.head = node.next
else:
prev.next = node.next
list = LinkedList()
list.AppendNode(1)
list.AppendNode(2)
list.AppendNode(3)
list.AppendNode(4)
list.PopNode(0)
list.PrintList( )
The output so far:
2
3
4
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
main()
File "<pyshell#31>", line 50, in main
list.PrintList( )
File "<pyshell#31>", line 27, in PrintList
node = node.next
AttributeError: 'Node' object has no attribute 'next'
I'm not sure why i'm getting the errors, since the code is technically working. Also any input on the insert, and index functions would be greatly appreciated.
For insert and index methods you will need another Node attribute, because you'll need to keep track of which item is on what position. Let we call it position. Your Node class will now look like this:
class Node:
def __init__(self, data, position = 0):
self.data = data
self.next_node = None
self.position = position
Retrieving index value now is easy as:
def index(self,item):
current = self.head
while current != None:
if current.data == item:
return current.position
else:
current = current.next
print ("item not present in list")
As for the list-altering methods, I would start with a simple add method which adds items to the leftmost position in the list:
def add(self,item):
temp = Node(item) #create a new node with the `item` value
temp.next = self.head #putting this new node as the first (leftmost) item in a list is a two-step process. First step is to point the new node to the old first (lefmost) value
self.head = temp #and second is to set `LinkedList` `head` attribute to point at the new node. Done!
current = self.head #now we need to correct position values of all items. We start by assigning `current` to the head of the list
self.index_correct(current) #and we'll write helper `index_correct` method to do the actual work.
current = self.head
previous = None
while current.position != self.size() - 1:
previous = current
current = current.next
current.back = previous
self.tail = current
What shall the index_correct method do? Just one thing - to traverse the list in order to correct index position of items, when we add new items (for example: add, insert etc.), or remove them (remove, pop, etc.). So here's what it should look like:
def index_correct(self, value):
position = 0
while value != None:
value.position = position
position += 1
value = value.next
It is plain simple. Now, let's implement insert method, as you requested:
def insert(self,item,position):
if position == 0:
self.add(item)
elif position > self.size():
print("position index out of range")
elif position == self.size():
self.AppendNode(item)
else:
temp = Node(item, position)
current = self.head
previous = None
while current.position != position:
previous = current
current = current.next
previous.next = temp
temp.next = current
temp.back = previous
current.back = temp
current = self.head
self.index_correct(current)
Below is the implementation that I could come up with (tested and working). It seems to be an old post, but I couldn't find the complete solution for this anywhere, so posting it here.
# add -- O(1)
# size -- O(1) & O(n)
# append -- O(1) & O(n)
# search -- O(n)
# remove -- O(n)
# index -- O(n)
# insert -- O(n)
# pop -- O(n) # can be O(1) if we use doubly linked list
# pop(k) -- O(k)
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setNext(self, newnext):
self.next = newnext
class UnorderedList:
def __init__(self):
self.head = None
self.tail = None
self.length = 0
def isEmpty(self):
return self.head is None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
if self.tail is None:
self.tail = temp
self.length += 1
def ssize(self): # This is O(n)
current = self.head
count = 0
while current is not None:
count += 1
current = current.getNext()
return count
def size(self): # This is O(1)
return self.length
def search(self, item):
current = self.head
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def remove(self,item):
current = self.head
previous = None
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
# The item is the 1st item
self.head = current.getNext()
else:
if current.getNext() is None:
self.tail = previous # in case the current tail is removed
previous.setNext(current.getNext())
self.length -= 1
def __str__(self):
current = self.head
string = '['
while current is not None:
string += str(current.getData())
if current.getNext() is not None:
string += ', '
current = current.getNext()
string += ']'
return string
def sappend(self, item): # This is O(n) time complexity
current = self.head
if current:
while current.getNext() is not None:
current = current.getNext()
current.setNext(Node(item))
else:
self.head = Node(item)
def append(self, item): # This is O(1) time complexity
temp = Node(item)
last = self.tail
if last:
last.setNext(temp)
else:
self.head = temp
self.tail = temp
self.length += 1
def insert(self, index, item):
temp = Node(item)
current = self.head
previous = None
count = 0
found = False
if index > self.length-1:
raise IndexError('List Index Out Of Range')
while current is not None and not found:
if count == index:
found = True
else:
previous = current
current = current.getNext()
count += 1
if previous is None:
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current)
previous.setNext(temp)
self.length += 1
def index(self, item):
pos = 0
current = self.head
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
pos += 1
if not found:
raise ValueError('Value not present in the List')
return pos
def pop(self, index=None):
if index is None:
index = self.length-1
if index > self.length-1:
raise IndexError('List Index Out Of Range')
current = self.head
previous = None
found = False
if current:
count = 0
while current.getNext() is not None and not found:
if count == index:
found = True
else:
previous = current
current = current.getNext()
count += 1
if previous is None:
self.head = current.getNext()
if current.getNext() is None:
self.tail = current.getNext()
else:
self.tail = previous
previous.setNext(current.getNext())
self.length -= 1
return current.getData()
def insert(self,item,position):
if position==0:
self.add(item)
elif position>self.size():
print("Position index is out of range")
elif position==self.size():
self.append(item)
else:
temp=Node.Node(item,position)
current=self.head
previous=None
current_position=0
while current_position!=position:
previous=current
current=current.next
current_position+=1
previous.next=temp
temp.next=current
Notice that in the Node class you defined the "next" field as "next_node". Therefore the interpreter doesn't know "next". So, instead of node.next it should be node.next_node

Categories

Resources