I am working on the implementation of Queue with a circularly linked list in python. Below is the pictorial representation of circularly LinkedList
I was able to implement most of the code except the dequeue routine. In dequeue routine, one has to keep track of the previous node reference as well as the next node reference with respect to current node. In double linked list, it's easy to implement. However, I have no idea how to implement this concept in single linked list.
class CircularQueue:
''' Queue implementation using a Circularly linked list for storage '''
class _Node:
__slots__ == '_element','_next'
def __init__(self,element,next):
self._element = element
self._next = next
def __init__(self):
'''Create an empty queue'''
self._current = None
self._size = 0
def __len__(self):
return self._size
def is_empty(self):
return self._size == 0
def enqueue(self,e):
node = self._Node(e,None)
if self.is_empty():
newest._next = newest
else:
curr_node = self._current._next
node._next = curr_node
self._current = node
self._size += 1
def dequeue(self):
if self.is_empty():
raise Empty('Stack is empty')
It would be more helpful if anyone can give me thoughts on how to move forward in dequeue routine.
Since your linked list is unidirectional, an element does only have a reference to it's successor, but never to it's predecessor, which you would need both in order to easily close the hole in the list once you dequeue an element.
I see two possibilities: You could either make the linked list bidirectional, therefore adding a reference to the previous element. I cleaned up your implementation a bit, I hope you still can make something of this:
""" Queue implementation using a Circularly linked list for storage """
class _Node:
def __init__(self, element, next=None, previous=None):
self.element = element
if next is None:
next = self
self.next = next
if previous is None:
previous = self
self.previous = previous
class CircularQueue:
def __init__(self):
self._current = None
self._size = 0
def __len__(self):
return self._size
def get_head(self):
return self._current.element
def is_empty(self):
return self._size == 0
def next(self):
self._current = self._current.next
return self._current.element
def previous(self):
self._current = self._current.pevious
return self._current
def enqueue(self, element):
""" Adds an element at the current position, ahead of the current element """
if self.is_empty():
new_node = _Node(element)
else:
new_node = _Node(element, self._current.next, self._current)
self._current.next = new_node
self._current = new_node
self._size += 1
We can now check if our code is correct:
cq = CircularQueue()
cq.enqueue("A")
cq.enqueue("B")
cq.enqueue("C")
print(cq.get_head())
print(cq.next())
print(cq.next())
print(cq.next())
And you will see C, A, B and C printed in succession.
A bilateral queue enables us to implement a dequeue method like this:
def dequeue(self, element_key=None):
if self.is_empty():
raise KeyError('Stack is empty')
if element_key is None:
self._current.next.previous = self._current.previous
self._current.previous.next = self._current.next
return self.next()
else:
current = self._current
while self._current.element != element_key:
self.next()
if self._current == current:
raise KeyError('Element not found')
self.dequeue()
And if we test it...
print("dequeuing 'B'")
cq.dequeue("B")
print(cq.get_head())
print(cq.next())
print(cq.next())
print(cq.next())
... we should see that "dequeuing 'B'" and C, A, C & again A are printed, which makes us happy. :)
Using a unilateral approach is possible too; you might end up having less work handling references while you would have run through your entire circle (in the worst case). First, you'd skip to the next element in the queue until the next element of the current one's is the one you want to dequeue, then set the current's elements next reference to the dequeued one's next, and you are basically done.
Related
When I implemet the dequeue() method, and in the following code
def dequeue(self):
if self.is_empty():
print("The Queue is empty")
return
answer = self._head._element
#---------------------
self._head = self._head._next #here, what happens with the "lost" node, because i think it is lost by the linked list
#---------------------
self._size -= 1
if self.is_empty():
self._tail = None
return answer
Is that node retrieved by the garbage collector?, because when i lost the reference to that node, and i have no way to access it.
The node is implemented as following within a LinkedList class.
class _Node:
__slots__ = "_element","_next"
def __init__(self, element, next):
self._element = element
self._next = next
Yep, it's a notation, and the garbage collector knows when to retrieve unused data.
I am reading Chapter 7 of Data Structures and Algorithms in Python and I am finding the Positional List ADT quite hard to understand, the implementation given by the book looks like this:
class _DoublyLinkedBase:
""" A base class providing a doubly linked list representation."""
class _Node:
__slots__ = '_element' , '_prev' , '_next' # streamline memory
def __init__(self, element, prev, next): # initialize node’s fields
self._element = element # user’s element
self._prev = prev # previous node reference
self._next = next # next node reference
# MAIN METHODS
def __init__(self):
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer # trailer is after header
self._trailer._prev = self._header # header is before trailer
self._size = 0 # number of elements
def __len__(self):
return self._size
def is_empty(self):
return self._size == 0
def _insert_between(self, e, predecessor, successor):
newest = self._Node(e, predecessor, successor) # linked to neighbors
predecessor._next = newest
successor._prev = newest
self._size += 1
return newest
def _delete_node(self, node):
predecessor = node._prev
successor = node._next
predecessor._next = successor
successor._prev = predecessor
self._size -= 1
element = node._element # record deleted element
node._prev = node._next = node._element = None # deprecate node
return element # return deleted element
class PositionalList(_DoublyLinkedBase):
""" A sequential container of elements allowing positional access."""
#-------------------------- nested Position class --------------------------
class Position:
""" An abstraction representing the location of a single element."""
def __init__(self, container, node):
""" Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
""" Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
""" Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def __ne__(self, other):
""" Return True if other does not represent the same location."""
return not (self == other) # opposite of eq
#-------------------------- End of nested Position class --------------------
#------------------------------- utility method -------------------------------
def _validate(self, p):
""" Return position s node, or raise appropriate error if invalid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._next is None: # convention for deprecated nodes
raise ValueError("p is no longer valid")
return p._node
#------------------------------- utility method -------------------------------
def _make_position(self, node):
""" Return Position instance for given node (or None if sentinel)."""
if node is self._header or node is self._trailer:
return None # boundary violation
else:
return self.Position(self, node) # legitimate position
#------------------------------- accessors -------------------------------
def first(self):
""" Return the first Position in the list (or None if list is empty)."""
return self._make_position(self._header._next)
def last(self):
""" Return the last Position in the list (or None if list is empty)."""
return self._make_position(self._trailer._prev)
def before(self, p):
""" Return the Position just before Position p (or None if p is first)."""
node = self._validate(p)
return self._make_position(node._prev)
def after(self, p):
""" Return the Position just after Position p (or None if p is last)."""
node = self._validate(p)
return self._make_position(node._next)
def __iter__(self):
""" Generate a forward iteration of the elements of the list."""
cursor = self.first( )
while cursor is not None:
yield cursor.element( )
cursor = self.after(cursor)
#------------------------------- mutators -------------------------------
# override inherited version to return Position, rather than Node
def _insert_between(self, e, predecessor, successor):
""" Add element between existing nodes and return new Position."""
node = super()._insert_between(e, predecessor, successor)
return self._make_position(node)
def add_first(self, e):
"""" Insert element e at the front of the list and return new Position."""
return self._insert_between(e, self._header, self._header._next)
def add_last(self, e):
""" Insert element e at the back of the list and return new Position."""
return self._insert_between(e, self._trailer._prev, self._trailer)
def add_before(self, p, e):
""" Insert element e into list before Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original._prev, original)
def add_after(self, p, e):
""" Insert element e into list after Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original, original._next)
def delete(self, p):
""" Remove and return the element at Position p."""
original = self._validate(p)
return self._delete_node(original) # inherited method returns element
def find(self, e):
if len(self) == 0:
raise ValueError('The list is empty')
position = self.first()
while position is not None:
element = position.element()
if element == e:
return position
position = self.after(position)
My question is about the position attribute. We can see that in the constructor of the Position class, there is a container attribute that never gets used explicitly, and this confuses me. I was thinking that maybe a position is something like an index that the user can use to access a certain node.
For instance, when I use the method find(e) to find an element e in the positional list, the method returns the position of the said element, and this position looks something like this:
<main.PositionalList.Position object at 0x7f43acade7f0>.
So I wonder what is the utility of the position if it is just an object and not an integer or string understandable by the user?
there is a container attribute that never gets used explicitly, and this confuses me
Actually, it is used: in the _validate method, which itself is used in several other methods.
Its purpose is to verify that a node -- that is passed to a container's before, after, add_before, add_after, or delete method -- is a node that already belongs to that container, without having to actually find it in the container, which would be a slow process.
I'm writing a linked list in Python and I've come across an issue which is really troublesome and terrible for debugging and I feel like I'm missing something about Python. I'm supposed to create a singly linked list with some basic functionalities. One of them is the take() function, which is meant to create a new list of n first elements of the original list.
However, creating a new instance of the LinkedList class seems to change the .self parameter and the variable node is modified, as the attribute .next is turned to None. In result, when creating a list and then trying to make a new one out of the n elements of it, the program runs indefinitely, but no matter which part I look at, I cannot find the loop or the reason behind it.
class LinkedList:
def __init__(self, head=None):
self.head = head
def is_empty(self):
if self.head == None:
return True
else:
return False
def add_last(self, node):
if self.is_empty():
self.head = node
return
nextEl = self.head
while True:
if nextEl.next is None:
nextEl.next = node
return
nextEl = nextEl.next
def take(self, n):
node = self.head
newHead = self.head
newHead.next = None
newList = LinkedList(newHead)
count = 0
while count < n:
newList.add_last(node.next)
node = node.next
count += 1
return newList
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
Thank you for all your help.
In the take() function the line
newHead.next = None
modifies a node of the linked list, breaking this list. You can fix this as follows:
def take(self, n):
node = self.head
newHead = Node(self.head.data)
newList = LinkedList(newHead)
count = 0
while count < n:
newList.add_last(node.next)
node = node.next
count += 1
return newList
This, however, still will not work correctly since there is a problem with the add_last() function too. This function, I think, is supposed to add a node as the last element of a linked list, but since you do not modify the next attribute of the node, you actually append a whole linked list starting with that node. This can be fixed in the following way:
def add_last(self, node):
if self.is_empty():
self.head = node
return
nextEl = self.head
while True:
if nextEl.next is None:
nextEl.next = Node(node.data)
return
nextEl = nextEl.next
There are more issues. For example, take(sefl, n) will actually create a list of n+1 elements and will throw an exception if it is applied to a linked list that does not have that many elements.
I am doing a Python program that implements linked list to support a few functions, one of the functions I need to do is to reverse a stack. I have made a Node, LinkedList and Stack classes, here is my Code so far:
class ListNode:
def __init__(self, Object):
self.Object = Object
self.next = None
class LinkedList:
def __init__(self):
self.head = None # first node
self.tail = None # last node
def addLast(self, Object):
newNode = ListNode(Object)
if self.head == None:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
self.tail = newNode
def removeFirst(self):
if self.head == None:
return
self.head = self.head.next
if self.head == None:
self.tail = None
def removeLast(self, Object):
if self.head == None:
return
current = self.head
prev = None
while current.next != None:
prev = current
current = current.next
if prev == None:
self.head = None
self.tail = None
else:
prev.next = None
self.tail = prev
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.next
return count
def isEmpty(self):
return self.head == None
def printList(self):
if self.head != None:
current = self.head
while current != None:
print(current.Object, end = ' ')
current = current.next
print()
# -------------------- STACK ---------------------------------------------------
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
def dequeue(self):
self.llist.removeFirst()
def queue(self, Object):
self.llist(Object)
def push(self, Object):
self.llist.addLast(Object)
def pop(self, Object):
self.llist.removeLast(Object)
def printStack(self):
self.llist.printList()
def size(self):
return self.llist.size()
def isEmpty(self):
return self.llist.isEmpty()
# ----------------------- Reverse LIST ------------------------------
def Reverse(S):
# S is a Stack Object
Here is my attempt at the problem:
def rRecursive( self ) :
self._rRecursive( self.head )
def _reverseRecursive( self, n ) :
if None != n:
right = n.next
if self.head != n:
n.next = self.head
self.head = n
else:
n.next = None
self._rRecursive( right )
def Reverse(S):
s.rRecursive()
If this was an ordinary list I could easily reverse it using [::-1] but I cannot since the linkedlist is an object. I was thinking maybe I could use temporary values so I can someone append the beginning of the stack to a list and then somehow convert it back into a stack object.
Edit for duplication: The goal of my program is use an existing Stack and reverse it. The linked post deals with a linked list that was already in a list format.
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
Edit 2: added my get function.
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
# push method implementation
def push(self, Object):
self.llist.addLast(Object)
def pop1(self):
self.llist.removeLast1()
def Reverse(S):
new_stack = Stack()
while not S.isEmpty():
new_stack.push(S.front())
S.pop1()
return new_stack
# Current Stack after Push: 12 14 40 13
# Stack after Pop: 12 14 40
# Stack after Reversal: 12 12 12
Edit 3: Added a rework of my code, it returns back a wrong reversal with the first element over and over again.
It's quite easy to reverse a stack using basic stack operations. Pop each item off the old stack and push it onto a new one.
def reverse(stack):
new_stack = Stack()
while not stack.isEmpty():
new_stack.push(stack.front())
stack.pop()
return new_stack
You could do something similar to destructively reverse the LinkedList within the Stack while reusing the stack object itself, you'd just need to use the list operations rather than the stack operations that are aliased to them.
Speaking of stack operations, you'll probably find that your stack performs better if you push and pop from the front, rather than the back. Removing an item from the end of the linked list requires iterating over the whole list (to find the next-to-last node). In contrast, both adding and removing from the front are fast.
You shouldn't have to fiddle with link pointers in your reversal function. I assume that you have a pop() method and other basics with your stack; if not, then clone your removeFirst function to return the removed node.
Now, the recursive function is simple: pop the head of the list, reverse the remaining stack (if any), and add the popped node to the end. Does this handle your problem?
def reverseStack(self):
move_me = self.pop()
if not self.isEmpty():
return (self.reverseStack()).addLast(move_me)
else:
new_stack = Stack()
return new_stack.addLast(move_me)
Other approaches to solving this problem: Cheat.
Define a __iter__ method (which makes sense in any event; iteration is a core Python behavior) to make your type iterable. Simple example:
def __iter__(self):
cur = self.head
while cur is not None:
yield cur.Object
cur = cur.next
Then just do:
values = list(self) # Creates a list containing the current set of values
self.head = self.tail = None # Clear existing linked list
# Add back all the values in reverse order
for value in reversed(values):
self.addLast(value)
Sure, it's likely less efficient in memory allocation/deallocation overhead than doing it properly. But the effect is likely marginal, and it simplifies the implementation code dramatically.
Of course, doing it properly isn't that hard, it's just slightly more confusing (totally untested, but it should be close to right):
def reverse(self):
# Start at beginning, which will be new end
cur, last = self.head, None
# Reverse head and tail pointers in advance
self.head, self.tail = self.tail, self.head
# Traverse while reversing direction of each node pointer
while cur is not None:
# Tuple pack and unpack allows one-line variable swap
cur.next, cur, last = last, cur.next, cur
The usual algorithm for reversing things using basic data structures is to use the fact that a stack is a first in last out data structure. That means if you pop until the stack is empty, you will get the items in the opposite order you pushed them on.
But it looks like you want to do this via recursive functions rather than an explicit stack - in this case, your function would normally fetch the front element,then recurse on the rest of the data structure, then handle that first element. This gets all the elements off in order, but handles them in the opposite order as each recursive call finishes and you work your way back up the call stack. If you neex to add the elements to a reversed data structure (and not just print them), you can build it up via return values by noticing that once you have the reverse if everything after the current element, you just need to attach that element to the front and you have the reverse of everything you were handed.
class Node(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def Reverse(head):
if head == None :
return None
elif head.next == None :
return head # returns last element from stack
else :
temp = head.next # stores next element while moving forward
head.next = None # removes the forward link
li = Reverse(temp) # returns the last element
temp.next = head # now do the reverse link here
return li
def main() :
temp4 = Node(4,None)
temp3 = Node(3,temp4)
temp2 = Node(2,temp3)
head = Node(1,temp2)
res = Reverse(head)
while res != None :
print(res.data)
res = res.next
main()
I just want to make sure that my getCount function will work, because I have no idea how to test this to make sure it works could someone tell me how I would either test this function or what I did wrong? It is supposed to count the number of times a certain object has occurred in my linked list.
Here is the ListNode import
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
.
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 getCount(self, position):
''' This function counts the amount of times a certain item is in the Linked List.'''
count = 0
if self.head == position:
count = 1
if self.head.link is None:
return count
return count + getCount(self.head.link, position)
def __copy__(self):
''' Post: Returns a new Linked List object that is a shallow copy of self.'''
a = LinkedList()
node = self.head
while node is not None:
a.append(node.item)
node = node.link
return a
#-----------------------------------------------------------------
def __iter__(self):
return LinkedListIterator(self.head)
#---------------------------------------------------------------------
class LinkedListIterator(object):
#-----------------------------------------------------------------
def __init__(self, head):
self.currnode = head
#-----------------------------------------------------------------
def next(self):
if self.currnode is None:
raise StopIteration
else:
item = self.currnode.item
self.currnode = self.currnode.link
return item
#-----------------------------------------------------------------
Hopefully I posted enough of my code for you guys to see the problem. I just want to find a way to test to see if my my count works and if it doesn't I need to know how to make it work.
Your LinkedList.getCount() method has several issues:
It tries to count self.head if it is equal to position, but self.head is a node, an instance of ListNode. It'll never be equal to a value you want to count.
It tries to use the method recursively, but there is no global getCount() function.
There is no need to use recursion here; just keep grabbing the next node from the 'current' until you run out, and compare against node.item each time:
def getCount(self, value):
count = 0
current = self.head
while current is not None:
if current.item == value:
count += 1
current = current.link
return count