Python doubly linked list - python

Please help me properly print my stackA class? Here is the current output. Also, how would I reverse the stackA?
C:\Users\Eli\PycharmProjects\GuessingGameReview\venv\Scripts\python.exe C:/Users/Eli/.PyCharmCE2019.2/config/scratches/Assignment_3.py
5
0
1
2
3
4
stackA is Empty!
[<__main__.Node object at 0x000001E54DEB0CC0>, <__main__.Node object at 0x000001E54DEB0C88>, <__main__.Node object at 0x000001E54DEB0C18>, <__main__.Node object at 0x000001E54DEB0BE0>, <__main__.Node object at 0x000001E54DEB0C50>]
[<__main__.Node object at 0x000001E54DEB0CC0>, <__main__.Node object at 0x000001E54DEB0C88>, <__main__.Node object at 0x000001E54DEB0C18>, <__main__.Node object at 0x000001E54DEB0BE0>, <__main__.Node object at 0x000001E54DEB0C50>]
[<__main__.Node object at 0x000001E54DEB0CC0>, <__main__.Node object at 0x000001E54DEB0C88>, <__main__.Node object at 0x000001E54DEB0C18>, <__main__.Node object at 0x000001E54DEB0BE0>, <__main__.Node object at 0x000001E54DEB0C50>]
Process finished with exit code 0
Process finished with exit code 0
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
self.prev = None
class doublelyLinkedList:
def __init__(self,head = None, tail = None,size = 0):
self.head = head
self.tail = tail
self.size = size
def push(self, e):
self.__data.append(e)
def pop(self):
if self.empty():
# raise Empty(stack is empty)
print("stack is empty")
return
return self.__data.pop()
def empty(self):
return len(self.__data) == 0
def removeHead(self, head):
temp = head
obj = head.data
head = head.next
temp.next = None
return obj
def removetail(self):
temp = self.head
while temp.next:
R = temp
temp = temp.next
self.tail = temp.prev
R.next = None
return temp
def append(self,data):
if self.head is None:
new_node = Node(data)
new_node.prev = None
self.head = new_node
else:
new_node = Node(data)
cur = self.head
while cur.next:
cur = cur.next
cur.next = new_node
new_node.prev = cur
new_node.next = None
def prepend(self,data):
if self.head is None:
new_node = Node(data)
new_node.prev = None
self.head = new_node
else:
new_node = Node(data)
self.head.prev = new_node
new_node.next = self.head
self.head = new_node
def __repr__(self):
nodes = []
curr = self.head
while curr:
nodes.append(repr(curr))
curr = curr.next
return '[' + ', '.join(nodes) + ']'
def isempty(self):
return self.head == None and self.tail == None
def print_list(self):
cur = self.head
while cur:
print(cur.data)
cur = cur.next
class deque:
def __init__(self):
self.dlist = doublelyLinkedList
def front_pop(self,e):
self.dlist.prepend(e)
def front_push(self):
if self.dlist.isempty():
print("deque is empty")
return
return self.dlist.removeHead()
def back_pop(self,e):
self.dlist.prepend(e)
def back_push(self,e):
if self.dlist.isempty():
print("deque is empty")
return
return self.dlist.removetail()
def __repr__(self):
return doublelyLinkedList. __repr__(self.dlist)
class stackA:
def __init__(self):
self.dlist = doublelyLinkedList()
def push(self, e):
self.dlist.prepend(e)
def pop(self):
if self.dlist.isempty():
print("stackA is Empty!")
return
return self.dlist.removeHead
def reverse_stack(self):
rev = Queue
curr = self.dlist.tail
while curr:
rev.enqueue(curr)
curr = curr.prev
self.list = rev.dlist
def __repr__(self):
return doublelyLinkedList.__repr__(self.dlist)
class Queue:
def __init__(self):
self.dlist = doublelyLinkedList()
def enqueue(self, e):
self.dlist.append(e)
def dequeue(self):
if self.dlist.isempty():
print("Queue is Empty!")
return
return self.dlist.removeHead()
def __repr__(self):
return doublelyLinkedList.__repr__(self.dlist)
def ReverseStack(t):
e = Queue()
while t.dlist.head != None:
e.enqueue(stackA.pop(t))
print("!!!!")
if __name__ == "__main__":
dlist = doublelyLinkedList()
dlist.prepend(0)
dlist.append(1)
dlist.append(2)
dlist.append(3)
dlist.append(4)
dlist.prepend(5)
dlist.print_list()
deque = deque()
stackA = stackA()
Queue = Queue()
# stack TEST
stackA.pop()
stackA.push("Obama")
stackA.push("Donald")
stackA.push("Bush")
stackA.push("Lincoln")
stackA.push("Roosevelt")
print(stackA)
stackA.pop()
print(stackA)
stackA.reverse_stack()
print(stackA)
print()

Your Node class needs a __repr__ method if you want repr(curr) in your dlist's __repr__ to yield something useful:
def __repr__(self):
return repr(self.data)
The reverseStack method has at least one basic syntax error that you'll need to fix before you can make any progress on that part of the problem.

Related

Put node class into linked list class python

This is my first time learning python
, just trying to create a simple linked list
here is the code
class node:
def __init__(self, data = None):
self.data = data
self.next = None
class linked_list:
def __init__(self):
self.head = node()
def append(self, data):
new_node = node(data)
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = new_node
def length(self):
cur = self.head
total = 0
while cur.next != None:
total += 1
cur = cur.next
return total
#property
def display(self):
elems = []
cur_node = self.head
while cur_node.next != None:
cur_node = cur_node.next
elems.append(cur_node.data)
print(elems)
def get(self, index):
if index >= self.length():
print('index out of range')
return None
cur_idx = 0
cur_node= self.head
while True:
cur_node = cur_node.next
if cur_idx == index: return cur_node.data
cur_idx+= 1
def erase(self, index):
if index >= self.length():
print('index out of range')
return None
cur_idx = 0
cur_node = self.head
while True:
last_node = cur_node
cur_node = cur_node.next
if cur_idx == index:
last_node.next = cur_node.next
return
cur_idx+= 1
l1 = linked_list()
l1.append(8)
l1.append(7)
l1.append(6)
l1.append(5)
print(l1.get(0))
print(l1.get(1))
print(l1.get(2))
print(l1.get(3))
everything went well except when I tried to put node class into linked list class as an inner class like below:
class linked_list:
class node:
def __init__(self, data = None):
self.data = data
self.next = None
def __init__(self):
self.head = node()
def append(self, data):
new_node = node(data)
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = new_node
......
(the rest are the same as the code above)
I got this error :
Traceback (most recent call last):
File "c:\blahblah\Basic_exercise.py", line 65, in <module>
l1 = linked_list()
File "c:\blahblah\Basic_exercise.py", line 11, in __init__
self.head = node()
NameError: name 'node' is not defined
1.what logic did I miss here?
2.Is there any way that I can treat node class as an inner class without getting errors?
The error you are seeing is due to the way you are referencing your innner class - it is a namespace issue. To disambiguate your inner node class from other node classes, you need to reference it by first using the outer class: linked_list.node.
Example:
class linked_list:
class node:
def __init__(self, data = None):
self.data = data
self.next = None
def __init__(self):
self.head = linked_list.node()
def append(self, data):
new_node = linked_list.node(data)
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = new_node
If you want to keep the node class inside the linked_list class then you need to call the node class from the linked list class. So to do that you must do new_node = linked_list.node(data) . Rest all should be the same

How can I add the second item in the linked list without overwriting the first one?

I've implemented a linked list in Python. The first item gets inserted properly. But the second one overwrites it in the head node. And after that it works just fine.
class Node:
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = Node()
self.iterator = self.head
def isEmpty(self):
if self.head.data is None:
return True
def insert(self, value):
if self.isEmpty():
self.head.data = value
else:
while self.iterator.next is not None:
self.iterator = self.iterator.next
self.iterator.next = Node()
self.iterator.data = value
self.iterator = self.head
def __str__(self):
l = []
while self.iterator.next is not None:
l.append(self.iterator.data)
self.iterator = self.iterator.next
self.iterator = self.head
return str(l)
t = LinkedList()
t.insert(2)
t.insert(4)
t.insert(8)
t.insert(6)
t.insert(10)
t.insert(12)
print(t)
Also in the str method how can I print the data if Head is the only node. (As Next of Head is None it will not enter the while loop.)
Here, you seem to overrwrite the data at self.iterator. Rather, you should set the data to the new node you created:
self.iterator.data = value
Fixed code:
class LinkedList:
def __init__(self):
self.head = Node()
self.iterator = self.head
def isEmpty(self):
if self.head.data is None:
return True
def insert(self, value):
if self.isEmpty():
self.head.data = value
else:
while self.iterator.next is not None:
self.iterator = self.iterator.next
new_node = Node()
new_node.data = value
self.iterator.next = new_node
self.iterator = self.head
Adding self.iterator.next = Node() inside the if statement of the method insert solved it for me:
class Node:
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = Node()
self.iterator = self.head
def isEmpty(self):
if self.head.data is None:
return True
def insert(self, value):
if self.isEmpty():
self.head.data = value
self.iterator.next = Node()
else:
while self.iterator.next is not None:
self.iterator = self.iterator.next
self.iterator.next = Node()
self.iterator.data = value
self.iterator = self.head
def __str__(self):
l = []
while self.iterator.next is not None:
l.append(self.iterator.data)
self.iterator = self.iterator.next
self.iterator = self.head
return str(l)
Output:
[2, 4, 8, 6, 10, 12]

Python LinkedList Garbage Collector

My question is, will the object Node(3) still be in RAM memory once we reach the end of remove() function ? If no, when is it deleted from RAM memory ?
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def add(self, data):
if self.head is None:
self.head = Node(data)
else:
curr_node = self.head
while (curr_node.next):
curr_node = curr_node.next
curr_node.next = Node(data)
def remove(self, data):
if self.head is not None:
if self.head.data == data:
self.head = self.head.next
else:
curr_node = self.head
while curr_node.next is not None:
if curr_node.next.data == data:
curr_node.next = curr_node.next.next
break
curr_node = curr_node.next
l = LinkedList()
l.add(2)
l.add(3)
l.add(4)
l.remove(3)
# program going on ...

Python printing the value of the variable show <__main__.Element object at 0x10071d5d0>

Hi I am trying to print the value of "temp" variable so I use print(temp)
def delete_first(self):
if self.head:
deleted_element = self.head
temp = deleted_element.next
print(temp)
self.head = temp
return deleted_element
else:
return None
Why do I get an output like this? Is this that the object address in the memory? do I fix it so that it prints out more meaningful/readable object names?
<__main__.Element object at 0x10071d5d0>
Full code:
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):
new_element.next = self.head
self.head = new_element
def delete_first(self):
if self.head:
deleted_element = self.head
temp = deleted_element.next
print(temp)
self.head = temp
return deleted_element
else:
return None
class Stack(object):
def __init__(self, top=None):
self.ll = LinkedList(top)
def push(self, new_element):
self.ll.insert_first(new_element)
def pop(self):
return self.ll.delete_first()
# 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
Full output:
<main.Element object at 0x10071d5d0>
3
<main.Element object at 0x10071d590>
2
None
1
None
None
4
You need to define a __str__ method for this class (if you own it, of course), like the toString() in Java.
For example:
class Element():
attr_1 = 0
attr_2 = 0
def __str__(self):
return '%s, %s' % (self.attr_1, self.attr_2)

doubly Linked list iterator python

I am constructing a doubly linked list and I am struggling on construct a doubly linked list iterator method in PYTHON.
This is my code so far
class DoubleListNode:
def __init__(self,data):
self.data=data
self.prev = None
self.next= None
class ListIterator:
def __init__(self):
self._current = self.head
def __iter__(self):
return self
def next(self):
if self.size == 0 :
raise StopIteration
else:
item = self._current.data
self._current=self._current.next
return item
class DoublyLinkedList:
def __init__(self):
self.head= None
self.tail= None
self.size = 0
def add(self,data):
newnode= DoubleListNode(data)
self.size+=1
if self.head is None:
self.head = newnode
self.tail = self.head
elif data < self.head.data: # before head
newnode.next = self.head
self.head.prev= newnode
self.head= newnode
elif data > self.tail.data: # at the end
newnode.prev= self.tail
self.tail.next= newnode
self.tail=newnode
else:
curNode = self.head
while curNode is not None and curNode.data < data:
curNode=curNode.next
newnode.next= curNode
newnode.prev=curNode.prev
curNode.prev.next= newnode
curNode.prev=newnode
def remove(self,data):
curNode=self.head
while curNode is not None and curNode.data!= data:
curNode= curNode.next
if curNode is not None:
self.size -= 1
if curNode is self.head:
self.head= curNode.next
else:
curNode.prev.next=curNode.next
if curNode is self.tail:
self.tail=curNode.prev
else:
curNode.next.prev=curNode.prev
When I run a test it said TypeError: iteration over non-sequence. Did I do something wrong ?
As posted, the code doesn't initialize (i.e. self.head isn't defined).
But overall, you are on the right track. Take a look at the source for Python's collections.OrderedDict for a worked-out example of traversing a doubly linked list.
Here's a simplified example:
class Link:
def __init__(self, value, prev=None, next=None):
self.value = value
self.prev = prev
self.next = next
def __iter__(self):
here = self
while here:
yield here.value
here = here.next
def __reversed__(self):
here = self
while here:
yield here.value
here = here.prev
if __name__ == '__main__':
a = Link('raymond')
b = Link('rachel', prev=a); a.next=b
c = Link('matthew', prev=b); b.next=c
print 'Forwards:'
for name in a:
print name
print
print 'Backwards:'
for name in reversed(c):
print name
I think there are two important things to fix.
First, your DoublyLinkedList class doesn't have an __iter__ method. You probably want to create one that returns a ListIterator instance. Perhaps you're trying to do this manually, but this would be the normal approach.
Second, you need to fix the code in your ListIterator to work properly. Currently your __init__ method doesn't initialize things correctly, and your next method tries to access member variables like size that don't exist.
Here's an implementation that I think will work:
def ListIterator(object):
def __init__(self, node):
self.current = node
def __iter__(self):
return self
def next(self):
if self.current is None:
raise StopIteration()
result = self.current.data
self.current = self.current.next
return result
class DoublyLinkedList(object):
# all your current stuff, plus:
def __iter__(self):
return ListIterator(self.head)
As a side note, in your current code you're defining classes with no bases. This is fine in Python 3 (where object will be the base by default), but in Python 2 this will result in getting an "old-style" class. Old-style classes are deprecated, and you'll find that some language features won't work properly with them (though not any of the features involved in iteration, as far as I know). On the other hand, if you are already using Python 3 then you need to define a __next__ method in the iterator class, rather than next (without the underscores).
Here is an example for Doubly Linked List class.
class Node:
def __init__(self, val):
self.data = val
self.next = None
self.prev = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self.count = 0
def insert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.head.prev = newNode
newNode.next = self.head
self.head = newNode
self.count += 1
def insertToEnd(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
newNode.prev = self.tail
self.tail = newNode
self.count += 1
def search(self, val):
p = self.head
while p is not None:
if p.data == val:
return p
p = p.next
def delete(self, val):
curNode = self.head
while curNode != None:
if curNode.data == val:
if curNode.prev != None:
curNode.prev.next = curNode.next
else:
self.head = curNode.next
if curNode.next != None:
curNode.next.prev = curNode.prev
else:
self.tail = curNode.prev
self.count -= 1
curNode = curNode.next
def show(self):
s = ""
p = self.head
while p is not None:
s += str(p.data) + ' ';
p = p.next
print(s + "| count: " + str(self.count))
Based on what you post, may I suggest:
class ListIterator:
# other stuff ...
def __iter__(self):
while self._current:
yield self._current.data
self._current = self._current.next
self._current = self.head # Reset the current pointer
You don't have to implement next()
Update
Here is an example usage:
for data in myListIterator:
print data
# Without reset, the second time around won't work:
for data in myListIterator:
print data

Categories

Resources