Stack pop using linked list - Python - python-3.x

I am trying to pop an item off a stack (using a linked list as oppose to an array). I first created a LinkedList class with 3 nodes with the values [1,2,3]. So I would like pop off the last node (node_C, value=3), therefore I expect to see the values [1,2]. Instead nothing prints out.
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
def pop(head):
current_node = head
while current_node.next:
if current_node.next == None:
break
else:
current_node = current_node.next
del current_node
return node_A.value, node_B.value, node_C.value
try:
print(pop(node_A))
except NameError:
pass
How can I rewrite this to achieve my desired results (i.e. show values 1,2 .. with 3 popped off)?

The del current node and return node_A.value, node_B.value, node_C.value
commands should belong to the pop function, so they should be intended. But anyway the del current node doesnt work for me. Instead you could write current_node.value = None but then you still return all 3 node values so the result would be 1,2,None.
I would rather write the pop function inside the class and add another printlist function to the class as well. The pop function just removes the last element from the list (changes the next attribute to None for the 2nd last element in the list) and doesn't print or return anything. The printlist function iterates through the list and prints out all elements (while there are next elements). Here is my code:
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def pop(self):
current_node = self
while current_node.next:
if current_node.next.next == None:
current_node.next = None
else:
current_node = current_node.next
def printlist(self):
current_node = self
lst = [current_node.value]
while current_node.next:
current_node = current_node.next
lst.append(current_node.value)
print lst
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
try:
node_A.pop()
node_A.printlist()
except NameError:
pass
If I run this, the result is [1,2]. If I remove the node_A.pop() I get [1,2,3]. If I write another node_A.pop() then result is [1]

I guess I have found the issue with your logic, so based on the code provided it seems that pop function doesn't return anything, may be it's just formatting or something else.
But here is the correct version of your code, where I just delete the last node in the pop method and I call another method called listValues which returns me with the node values that exist in the linked list after pop
Look at the below implementation for a clearer view.
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
node_A = LinkedList(1)
node_B = LinkedList(2)
node_C = LinkedList(3)
node_A.next = node_B
node_B.next = node_C
def pop(head):
current_node = head
while current_node.next:
if current_node.next == None:
del current_node
break
else:
current_node = current_node.next
def listValues(head):
values = []
current_node = head
while current_node.next:
values.append(current_node.value)
current_node = current_node.next
return values
try:
pop(node_A)
print(listValues(node_A))
except NameError:
pass
Hope this helps!

Related

code should not return any node object(Element)

https://gist.github.com/manaidu-2002/3f7eb60b8521201eba6548ca23cec053
Code returning Node Object(Element), please check the test cases and help me with this
"""Add a couple methods to our LinkedList class,
and use that to implement a Stack.
You have 4 functions below to fill in:
insert_first, delete_first, push, and pop.
Think about this while you're implementing:
why is it easier to add an "insert_first"
function than just use "append"?"""
class Element(object):
def __init__(self, value):
self.value = value
self.next = None
class LinkedList(object):
def __init__(self, head=None):
self.head = head
def append(self, new_element):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_element
else:
self.head = new_element
def insert_first(self, new_element):
"Insert new element as the head of the LinkedList"
new_element.next = self.head
self.head = e_insert
def delete_first(self):
"Delete the first (head) element in the LinkedList as return it"
temp = self.head
if temp == None:
return None
s= temp
self.head = temp.next
return s
class Stack(object):
def __init__(self,head=None):
self.ll = LinkedList(head)
def push(self, new_element):
"Push (add) a new element onto the top of the stack"
temp = self.ll.head
while temp.next :
temp = temp.next
temp.next = new_element
def pop(self):
"Pop (remove) the first element off the top of the stack and return it"
if self.ll.head.next == None :
temp = self.ll.head
e= temp
temp = None
return e
elif self.ll.head.next:
temp = self.ll.head
while temp.next.next:
temp = temp.next
e= temp.next
temp.next = None
return e
return None
# Test cases
# Set up some Elements
e1 = Element(1)
e2 = Element(2)
e3 = Element(3)
e4 = Element(4)
# Start setting up a Stack
stack = Stack(e1)
# Test stack functionality
stack.push(e2)
stack.push(e3)
print(stack.pop().value)
print(stack.pop().value)
print(stack.pop().value)
print(stack.pop())
stack.push(e4)
print(stack.pop().value)
First of all, there is an unused name reference in your code: e_insert. This should read new_element.
The main issue is that your Stack class is not re-using the code you already have in your LinkedList class. In the new code you have written there are several mistakes in how you deal with next, but taking a step back, you are making a critical mistake in thinking that the top of the stack should be at the tail of the linked list, but that is very inefficient. The top of the stack should be at the head of the linked list. It is at that side that you can easily remove and insert elements without having to iterate the list.
So take these points into consideration:
Reuse the code you already have for LinkedList. In other words, call the methods defined on the LinkedList class.
The top of the stack is at the head of the linked list.
That means the Stack class can be as simple as this:
class Stack(LinkedList):
def __init__(self, head=None):
self.ll = LinkedList(head)
def push(self, new_element):
self.ll.insert_first(new_element)
def pop(self):
return self.ll.delete_first()

AttributeError: 'LinkedList' object has no attribute 'head'

I don't understand what is wrong with my code. it says
AttributeError: 'LinkedList' object has no attribute 'head'
Here is my code:
class Node:
def __init__(self, data):
self.data = data
self.next = None
I created an empty linked list and added nodes:
class LinkedList():
def __int__(self):
self.head = None
def insert(self, newNode):
if self.head is None:
self.head = newNode
else:
#head =>john->Ben->Matthew->None
lastNode = self.head
while True:
if lastNode.next is None:
break
lastNode = lastNode.next
lastNode.next = newNode
def printList(self):
#head=>john->Ben->Matthew->None
currentNode = self.head
while True:
if currentNode is None:
break
print(currentNode.data)
currentNode = currentNode.next
# node => data, next
#firstnode.data => data, firstnode.next => None
firstNode = Node('john')
linkedlist = LinkedList()
linkedlist.insert(firstNode)
secondNode = Node('Ben')
linkedlist.insert(secondNode)
thridNode = Node('Matthew')
linkedlist.insert
linkedlist.printList()
You have some errors which you could easily spot with some debugging (stepping through the code):
The LinkedList function __int__ is never executed (you could spot this by putting a breakpoint there). It should be named __init__.
The main program does not add the third node, because it does not call the insert method -- it merely references it. You could spot this easily when stepping through the code, one instruction at a time, with a debugger. Add the parentheses and pass the argument.
The printList has a loop that runs infinitely, because the line that moves the currentNode reference is not part of the loop's body. You could spot this easily again by stepping through the code with a debugger. This statement should be indented more to become part of the loop.
This should fix your problems.
Note: this was just a matter of debugging. You really can do this yourself in a good programming environment.

Linked list implementation in python

I am learning how to use linked lists, and would like to add a value, remove a value, and test if a value is in the linked list. I am struggling to work out how test for a value and remove a value.
class Node(object):
def __init__(self, v, n):
self.value = v
self.next = n
class LinkedList(object):
def __init__(self):
self.firstLink = None
def add (self, newElement):
self.firstLink = Node(newElement, self.firstLink)
def test(self, testValue):
def remove(self, testValue):
To test if a value is in a LinkedList you have to go through the list and check every item
def contains(self, testValue):
ptr = self.firstLink
while ptr != None:
if ptr.value == testValue:
return True
ptr = ptr.next
return False
When using remove() method you usually don't pick an item to be removed. Remove method should only remove the last item added to LinkedList. Last in, First out.
def remove(self):
if self.firstLink == None():
return None
else:
item = self.firstLink.value
self.firstLink = self.firstLink.next
return item
To learn more about Linked Lists or see how can 'remove element' from LinkedList be implemented in python go to this site. It is well explained in there LinkedList

binary search tree - recursive insertion python

I'm trying to correctly construct a binary search tree with a recursive insert function that will allow me to initialize a tree and continue to add nodes (stems). Here is the code that I've done so far (newer to coding, so probably way too wordy):
class Binary_Search_Tree:
class __BST_Node:
def __init__(self, value):
self.value = value
self.right_child = None
self.left_child = None
def __init__(self):
self.__root = None
self.__height = 0
self.value = None
def _recursive_insert(self, value):
new_stem = Binary_Search_Tree.__BST_Node(value)
if self.__root is None:
self.__root = new_stem
self.__root.value = new_stem.value
else:
if self.__root.value > new_stem.value:
if self.__root.right_child is None:
self.__root.right_child = new_stem
self.__root.right_child.value = new_stem.value
else:
self.__root.right_child._recursive_insert(self.__root, value)
else:
if self.__root.left_child is None:
self.__root.left_child = new_stem
self.__root.left_child.value = new_stem.value
else:
self.__root.left_child._recursive_insert(self.__root, value)
def insert_element(self, value):
element_to_insert = self._recursive_insert(value)
return element_to_insert
I then try to add values to this new tree in the main method:
if __name__ == '__main__':
new = Binary_Search_Tree()
new.insert_element(23)
new.insert_element(42)
new.insert_element(8)
new.insert_element(15)
new.insert_element(4)
new.insert_element(16)
The error that I keep getting is: '__BST_Node' object has no attribute '_recursive_insert' This pops up after inserting the first element, so I'm guessing the error occurs somewhere in the else statement. If anyone can figure out where my error is or has any tips on how to make this code more readable/user friendly, I'd be appreciative!
The issue is with this line:
self.__root.right_child._recursive_insert(self.__root, value)
As well as this:
self.__root.left_child._recursive_insert(self.__root, value)
You've defined _recursive_insert to be a method of Binary_Search_Tree, but you're calling it with an instance of __BST_Node, in self.__root.xxxxx_child._recursive_insert, where xxxx_child is an instance of BST_Node.
In fact, your entire _recursive_insert function leaves something to be desired. You're not returning anything from it, but you are assigning it's (non-existent) return value to something in insert_element.
Fixed code:
def _recursive_insert(self, root, value):
new_stem = Binary_Search_Tree.__BST_Node(value)
if root is None:
root = new_stem
else:
if root.value < new_stem.value:
if root.right_child is None:
root.right_child = new_stem
else:
root = self._recursive_insert(root.right_child, value)
elif root.value > new_stem.value:
if root.left_child is None:
root.left_child = new_stem
else:
root = self._recursive_insert(root.left_child, value)
return root
def insert_element(self, value):
self.__root = self._recursive_insert(self.__root, value)
return element_to_insert
Your function did not return an updated root
Your function does not handle a case when the value being inserted would be equal to an existing value, causing spurious entries.
With each recursive call, your function was being passed the same values, so it would not be able to know what to do. A new parameter for the node must be passed across calls. This makes it possible to establish a base case and return.

Cant insert item at start of linked list - python

I'm currently learning about linked lists for a class and ran into trouble.
I have to be able to insert an item before a specified item so
(Apple,banana,pear)before pear would be (Apple,banana,newItem,pear)
and I managed this with this code:
def insert_before(head,data,location):
current = head
found = False
while not found:
if current.next.data == location:
new_node = Node(data)
new_node.next = current.next
current.next = new_node
found = True
else:
current = current.next
But my issue arose when trying to insert an item before the first item in the list, to try this I thought of doing it as such:
if head.data == location:
new_node = Node(data)
head.next = head.next
new_node.next = head`
But this doesn't seem to work. Any guides I found on here were to add an item AFTER the first item, any tips would be appreciated.
In the provided source code, the use of head.next = head.next do nothing and doesn't change the value of the head node.
To modify the value of the first node in a linked list by inserting a new node before, it is necessary update the head variable.
Solution 1 - assign the head as the returned value of the insert_before() function.
The variable previous is used to modify the node before and when is
= None, the first node must be modified.
def insert_before(head,data,location):
current = head
previous = None
found = False
while not found:
if (current != None):
if (current.data == location):
new_node = Node(data)
if (previous != None):
new_node.next = previous.next
previous.next = new_node
else:
new_node.next = head
head = new_node
found = True
else:
previous = current
current = current.next
else:
print('location ',location,' not found.')
break
return head
The use of the function becomes:
myhead = Node(5)
print(myhead.data) # >> 5
myhead = insert_before(myhead,3,5)
print(myhead.data) # >> 3
print(myhead.next.data) # >> 5
Solution 2 - use the OOP of Python by adding a headattribute in the Node class.
The OOP approach is quite similar, but instead of storing the head
node outside the function, the function insert_before() is added to
the class Node.
Step 1 - add in the class Node the attribute head.
class Node(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
self.head = self # store the first node
Step 2 - use the internal self.head instead of the head as parameter
In that case, when the new node shall be inserted before the first
node, the assignment is very simple self.head = new_node.
def Insert_Before(self,data,location):
current = self.head
previous = None
found = False
print('insert ',data,' before ',location)
while not found:
if (current != None):
if (current.data == location):
new_node = Node(data)
if (previous != None):
new_node.next = previous.next
previous.next = new_node
else:
new_node.next = self.head
self.head = new_node # update the first node
found = True
else:
previous = current
current = current.next
else:
print('location ',location,' not found.')
break
return
The use of the function becomes:
myhead = Node(5)
print(myhead.data)
myhead.insert_before(3,5)
print(myhead.head.data)
print(myhead.head.next.data)
Warning: instead of using myhead as the first node, use the
myhead.head attribute.

Resources