Circular Array-Based Queue Insert Class Method - Python - python

I am trying to implement the insert method of a circular array-based queue, however am unable to update the rear of the queue. Here is my code:
def __init__(self, max_size):
"""
-------------------------------------------------------
Initializes an empty queue. Data is stored in a fixed-size list.
Use: cq = Queue(max_size)
-------------------------------------------------------
Parameters:
max_size - maximum size of the queue (int > 0)
Returns:
a new Queue object (Queue)
-------------------------------------------------------
"""
assert max_size > 0, "Queue size must be > 0"
self._max_size = max_size
self._values = [None] * self._max_size
self._front = 0
self._rear = 0
self._count = 0
def insert(self, value):
'''-------------------------------------------------------
Adds a copy of value to the rear of the queue.
Use: cq.insert( value )
-------------------------------------------------------
Parameters:
value - a data element (?)
Returns:
None
-------------------------------------------------------'''
assert (self._count < self._max_size), 'queue is full'
self._values.append(deepcopy(value))
self._count += 1
self._rear = (self._rear - 1) % self._count
return
Any suggestions?
edit:
here is the remove implementation:
def remove(self):
'''-------------------------------------------------------
Removes and returns value from the queue.
Use: v = cq.remove()
-------------------------------------------------------
Returns:
value - the value at the front of the queue - the value is
removed from the queue (?)
-------------------------------------------------------'''
assert (self._count > 0), 'Cannot remove from an empty queue'
value = self._values[self._front]
self._front = (self._front + 1) % self._count
self._count += -1
return value

When you add items by appending, you are extending your list beyond the max length that you pre-allocated it to. You then update self._rear as if you were going to use it as the insert index, but never actually use it for anything. I have implemented your code with only very minor changes beyond variable names (in order to make more sense to me), and utilizing self._rear (now: self._write_cursor) in the way I believe you intended.
class CQ: #Circular Queue
def __init__(self, maxsize):
self._maxsize = maxsize
self._write_cursor = 0
self._read_cursor = 0
self._len = 0
self._values = [None] * maxsize
def insert(self, item):
if self._len < self._maxsize:
self._values[self._write_cursor] = item
self._write_cursor = (self._write_cursor + 1) % self._maxsize
self._len = self._len + 1
else:
raise IndexError('can\'t push to full queue')
def remove(self):
if self._len > 0:
out = self._values[self._read_cursor]
self._read_cursor = (self._read_cursor + 1) % self._maxsize
self._len -= 1
return out
else:
raise IndexError('can\'t pop from empty queue')

Related

Ternary Max Heap Python

I am trying to turn a Binary Max Heap into a Ternary Max Heap in Python. My code needs to remain in the same structure as the binary heap below. I need some help figuring out what changes to make. I know the max child method needs to be updated with 3 * i - 1,
3 * i, and 3 * i + 1. I don't know where to begin. Any suggestions would be appreciated.
class BinaryMaxHeap:
def __init__(self):
'''
heap_list[0] = 0 is a dummy value (not used)
'''
self.heap_list = [0]
self.size = 0
def __str__(self):
'''
returns the string representation of the object
'''
return str(self.heap_list)
def __len__(self):
'''
returns a positive integer that represents the length of the object
'''
return self.size
def __contains__(self, item):
'''
instance method, returns boolean value
'''
return item in self.heap_list
def is_empty(self):
'''
compare the size attribute to 0
'''
return self.size == 0
def find_max(self):
'''
the largest item is at the root node (index 1)
'''
if self.size > 0:
max_val = self.heap_list[1]
return max_val
return None
def insert(self, item):
'''
append the item to the end of the list (maintains complete tree property)
violates the heap order property
call percolate up to move the new item up to restore the heap order property
'''
self.heap_list.append(item)
self.size += 1
self.percolate_up(self.size)
def del_max(self):
'''
max item in the tree is at the root
replace the root with the last item in the list (maintains complete tree property)
violates the heap order property
call percolate down to move the new root down to restore the heap property
'''
max_val = self.heap_list[1]
self.heap_list[1] = self.heap_list[self.size]
self.heap_list.pop()
self.size -= 1
self.percolate_down(1)
return max_val
def max_child(self, index):
'''
return the index of the largest child
if there is no right child, return the left child
if there are two children, return the largest of the two
'''
if index*2+1 > self.size:
return index * 2
else:
if self.heap_list[index*2] < self.heap_list[index*2+1]:
return index * 2
else:
return index*2+1
def build_heap(self, alist):
'''
build a heap from a list of keys to establish complete tree property
starting with the first non leaf node
percolate each node down to establish heap order property
'''
index = len(alist)//2 # any nodes past the halfway point are leaves
self.size = len(alist)
self.heap_list = [0] + alist[:]
while (index>0):
self.percolate_down(index)
index -= 1
def percolate_up(self, index):
'''
compare the item at index with its parent
if the item is greater than its parent, swap!
continue comparing until we hit the top of tree
(can stop once an item is swapped into a position where it is greater than its parent)
'''
while index // 2 > 0:
if self.heap_list[index] > self.heap_list[index//2]:
temp = self.heap_list[index//2]
self.heap_list[index//2] = self.heap_list[index]
self.heap_list[index] = temp
index //= 2
def percolate_down(self, index):
'''
compare the item at index with its largest child
if the item is less than its greatestest child, swap!
continue continue while there are children to compare with
(can stop once an item is swapped into a position where it is less than both children)
'''
while (index * 2) <= self.size:
mc = self.max_child(index)
if self.heap_list[index] < self.heap_list[mc]:
temp = self.heap_list[index]
self.heap_list[index] = self.heap_list[mc]
self.heap_list[mc] = temp
index = mc
While a dummy entry can still be interesting for a binary heap implementation, to get the same "benefit" for a ternary heap, you would need 2 dummies. It is better to just adapt the index calculations and have no dummy needs. Without the dummy it becomes also overkill to have a size attribute, since it always corresponds to the length of the list.
The implementation for a ternary tree just needs to adapt all those occurrences where a coefficient of 2 is used and adapt them to use 3 (and the shift to get the index right).
I would not have created a separate build_heap method, and certainly not as an instance method, but since you indicated you want the "same structure", I left it like that.
class TernaryMaxHeap:
def __init__(self):
self.heap_list = [] # No more dummy
# No more size attribute. A list knows its size.
def __str__(self):
return str(self.heap_list)
def __len__(self):
return len(self.heap_list)
def __contains__(self, item):
return item in self.heap_list
def is_empty(self):
return not self.heap_list
def find_max(self):
if self.heap_list:
return self.heap_list[0] # No more dummy
def insert(self, item):
self.heap_list.append(item)
self.percolate_up(len(self)-1)
def del_max(self):
max_val = self.heap_list[0]
self.heap_list[0] = self.heap_list[-1]
self.heap_list.pop()
if self.heap_list:
self.percolate_down(0)
return max_val
def max_child(self, index):
child = index * 3 + 1
if child >= len(self) - 1:
return child
# Generic with range, using coefficient 3
return max((self.heap_list[child], child) for child in range(child, min(child + 3, len(self))))[1]
# NB: This alist argument should have better been integrated with the constructor:
def build_heap(self, alist):
self.heap_list = alist[:] # No dummy
for index in range((len(alist) - 2)//3, -1, -1): # Use divisor 3, and pythonic looping
self.percolate_down(index)
def percolate_up(self, index):
val = self.heap_list[index]
parent = (index - 1) // 3 # Coefficient 3, without dummy
while index and self.heap_list[parent] < val:
self.heap_list[index] = self.heap_list[parent]
index = parent
parent = (index - 1) // 3
self.heap_list[index] = val
def percolate_down(self, index):
val = self.heap_list[index]
child = self.max_child(index)
while child < len(self) and val < self.heap_list[child]:
self.heap_list[index] = self.heap_list[child]
index = child
child = self.max_child(index)
self.heap_list[index] = val

Which dunder method (__method__) can replicate del obj[index] in custom data objects?

I am just experimenting with a hybrid model of Linked List with some modifications. I have already implemented object.delete_node(index) which just link the next node as it is in vanilla Linked Lists. Now, and want to implement del object[index] which does the same function as object.delete_node(index). How could I implement it? It is implemented in list and dict in Python. Which method is responsible for the same?
Below is the code for my LinkedList which works pretty well.
class Node:
def __init__(self, data = None, next_pointer = None):
self.data = data
self.next_pointer = next_pointer
def __str__(self):
return self.__repr__()
def __repr__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.head = Node()
self.length = 0
def insert_node(self, data):
new_node = Node(data) # node to be inserted
current_node = self.head
while current_node.next_pointer != None: # it'll only stop at the last node which is obviously empty
current_node = current_node.next_pointer # bring out next pointer
current_node.next_pointer = new_node
self.length += 1
def delete_node(self, index):
if self.length == 0: raise ValueError(f"Can not delete from empty Linked List")
if (index > self.length - 1) or (index < -self.length -1): raise ValueError(f"index {index} out of bounds of max length")
if index < 0: index = self.length + index
count = 0
current_node = self.head
while count < index:
current_node = current_node.next_pointer
count += 1
current_node.next_pointer = current_node.next_pointer.next_pointer if current_node.next_pointer.next_pointer != None else None
self.length -= 1
def _slice_return(self, slice_index):
'''
Implement slicing Operation just like in Python Lists and Strings
'''
index = slice_index.start
stop = min(slice_index.stop, self.length -1)
step = 1 if slice_index.step == None else slice_index.step
if index < 0: raise NotImplementedError("Negative slicing not implemented")
if (index > self.length - 1) or (index < -self.length -1): raise ValueError(f"index {index} out of bounds of max length")
if index < 0: index = self.length + index
ll = LinkedList()
for i in range(index, stop,step):
ll.insert_node(self[i].data)
return ll
def __getitem__(self, index):
if isinstance(index, slice):
return self._slice_return(index)
if (index > self.length - 1) or (index < -self.length -1): raise ValueError(f"index {index} out of bounds of max length")
if index < 0: index = self.length + index
count = 0
current_node = self.head.next_pointer
while count != index:
current_node = current_node.next_pointer
count += 1
return current_node
def __len__(self):
return self.length
def __str__(self):
array = []
node = self.head
count = self.length
while count > 0:
node = node.next_pointer
array.append(node.data)
count -= 1
return(str(array))
def __repr__(self):
return self.__str__()
ll = LinkedList()
ll.insert_node("a")
ll.insert_node("b")
ll.insert_node("A")
ll.insert_node("B")
ll.delete_node(2) # delete 3rd node
Answer based on #jonrsharpe comment:
There is a Datamodel section in python docs with list of available dunder methods
In your case its:
object.__delitem__(self, key)
Called to implement deletion of self[key]. Same note as for __getitem__(). This should only be implemented for mappings if the objects support removal of keys, or for sequences if elements can be removed from the sequence. The same exceptions should be raised for improper key values as for the __getitem__() method.

python linklist pointer and size

I am a rookie python programmer. I see the leetcode's definition of a linked list below. I got 2 questions for this concept, any help would be appreciated. Thanks in advance
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
Q1 Just wonder what is the type of the "self.next", I know in C++, it should be a pointer that represents the address of the next node. But python does not have that type, so I am confused what type "next" is.
Q2 Some tell me next is just a name. If that is the case, I run the code below,
head =ListNode(1)
print sys.getsizeof(head)
head.next = ListNode(2)
print sys.getsizeof(head)
first the head.next is 'None', and then it is assigned to another ListNode type,
but I get the same size of head before and after this change, which I think the size of head should be larger since one of its member (next) is changed from None type to ListNode type. I am just confused about this, thank you so much!
PS. In my understanding, if I keep adding new nodes to the linklist, the head will be larger and larger since there are more and more 'nested' member 'next', just point out where I get wrong, thanks.
Question 1:
Python variables are dynamically typed. (i.e. a variable could hold an int, and then hold a list, and then any other arbitrary object, etc).
In your case, Head.next starts by referencing, None a NoneType object.
After you assign it a different value (ListNode(2)), the Head.next now references the newly created ListNode object.
Question 2:
Why doesn't the size change.
I'm not an expert on how python's sys.getsizeof works, but from what I can gather, is that List.next in both cases is a reference variable (i.e. a variable that references some other object). The size doesn't change because sys.getsizeof finds the size of the object's variables. Where Head.next is just a reference to some other object in both cases.
See, How do I determine the size of an object in Python?, for more complete answers on how sys.getsizeof works.
My interpretation of a linked list.
class LinkedList(object):
class Node(object):
def __init__(self, val=None, next=None, previous=None):
self.val = val
self.next = next
self.last = previous
def __init__(self):
self.length = 0
self.start = None
self.end = None
def append(self, value):
self.length += 1
if not self.start:
self.start = self.Node(value)
else:
if not self.end:
self.end = self.Node(value)
self.end.previous = self.start
self.end.next = self.start
self.start.next = self.end
else:
end = self.Node(value)
self.end.next = end
end.previous = self.end
self.end = end
self.end.next = self.start
def prepend(self, value):
self.length += 1
if not self.start:
self.start = self.Node(value)
else:
n = self.Node(value, self.start, self.end)
self.start.previous = n
self.start = n
def __len__(self):
return self.length
def __iter__(self):
self.position = 0
return self
def next(self):
self.position += 1
if self.position-1 >= len(self):
raise StopIteration
if self.position-1 == 0:
return self.start
cnt = 0
n = self.start
while cnt<self.position-1:
n = n.next
cnt += 1
return n
def __getitem__(self, index):
if index == 0:
return self.start
if index == -1:
return self.end
cnt = 0
n = self.start
while cnt<index+1:
n = n.next
cnt += 1
return n.val
def __repr__(self):
return repr(tuple(x.val for x in self))
l = LinkedList()
l.append(4)
l.append(5)
l.append(3)
l.prepend(0)
print l
print l[1]

Circular Queue Structure ( array-backed)

I need some help in writing a python program that will implement a circular queue data structure (array-backed). I've completed a few of the methods already but I'm a bit stumped when it comes to adding and taking things away from the queue, as well as checking the values within it. I believe this is of the first-in-first-out structure. Here's what I have for the body so far
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.queue = []
self.head = -1
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
self.head = 0
x = self.queue.pop(0)
if self.head == self.tail:
self.head = -1
self.tail = -1
else:
self.tail -= 1
self.count -= 1
#self.head += 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.queue.append(item)
self.tail += 1
def __str__(self):
return " ".join([str(v) for v in self.queue])
def resize(self, new_limit):
new_q = [None]*self.limit
old_q = self.queue
for i in range(len(old_q)):
new_q[i] = old_q[i]
self.limit = new_limit
self.queue = new_q
def empty(self):
return 0 == self.count
def iter(self):
listt = []
for v in self.queue:
listt.append(v)
return listt
What I 've written thus far makes the most sense to me but if I were to test this with the following code block I'd get an error saying 10 != 4. This code will fail the 9th line of the test, tc.assertEqual(q.data.count(None), 4) I'm unsure why my code is producing the value 10 at this time. What would allow for this class to pass the given test?
from unittest import TestCase
tc = TestCase()
q = Queue(10)
for i in range(6):
q.enqueue(i)
tc.assertEqual(q.data.count(None), 4)
for i in range(5):
q.dequeue()
tc.assertFalse(q.empty())
tc.assertEqual(q.data.count(None), 9)
tc.assertEqual(q.head, q.tail)
tc.assertEqual(q.head, 5)
for i in range(9):
q.enqueue(i)
with tc.assertRaises(RuntimeError):
q.enqueue(10)
for x, y in zip(q, [5] + list(range(9))):
tc.assertEqual(x, y)
I'm pretty sure that all the code using self.queue is wrong. That attribute isn't needed at all. The whole point of the data attribute is to use it to store the values. Use the indexes head and tail to figure out where in data to put things (and where to take them from):
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.head = 0
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
x = self.data[self.head]
self.head = (self.head + 1) % self.limit
self.count -= 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.tail = (self.tail + 1) % self.limit
self.data[self.tail] = item
def __str__(self):
return " ".join([str(v) for v in self]) # use __iter__
def resize(self, new_limit):
if new_limit < self.count:
raise RuntimeError
new_data = [None]*new_limit
for i, item in enumerate(self):
new_data[i] = item
self.data = new_data
self.head = 0
self.tail = self.count - 1
def empty(self):
return 0 == self.count
def __bool__(self): # this is better than empty()
return self.count != 0
def __iter__(self): # renamed from iter so you can use it in a for loop
for i in range(self.count):
return self.data[(self.head + i) % self.limit]
You should probably also have a __len__ method.
I'd get an error stating that the Queue class doesn't have a data attribute
I don't have the error you mention when running your test on your code.
If for some reasons you don't want to use built-in collections.deque module, here is an example of how you can implement your own circular buffer:
"""
Example of circular buffer using regular list
"""
class CircularBuffer:
def __init__(self, size):
self.buffer = [None] * size
self.size = size
self.count = 0
self.tail = 0
self.head = 0
#property
def is_empty(self):
return self.count == 0
#property
def is_full(self):
return self.count == self.size
def __len__(self):
return self.count
def add(self, value):
# if buffer is full overwrite the value
if self.is_full:
self.tail = (self.tail + 1) % self.size
else:
self.count += 1
self.buffer[self.head] = value
self.head = (self.head + 1) % self.size
def remove(self):
if self.count == 0:
raise Exception("Circular Buffer is empty")
value = self.buffer[self.tail]
self.tail = (self.tail + 1) % self.size
self.count -= 1
return value
def __iter__(self):
index = self.tail
counter = self.count
while counter > 0:
yield self.buffer[index]
index = (index + 1) % self.size
counter -= 1
def __repr__(self):
return "[]" if self.is_empty else "[" + ",".join(str(i) for i in self) + "]"

How can I create a running average of the last N items in a time series?

My basic idea was to create a linked list, and as each new value comes in, add 1/N times the new value and subtract 1/N times the first value, then move the pointer to first along by one and free the memory that had been associated with first.
This won't ultimately be implemented in Python but just to get the process clear in my head, I tried to write it in Python, but my implementation is flawed. Do I need a doubly linked list for this? Is there an alternative approach (not linked-list based) that would be better?
Here's my attempt so far:
class Link:
def __init__(self,val):
self.next = None
self.value = val
class LinkedList:
def __init__(self,maxlength):
self.current_link = None
self.maxlength = maxlength
self.sum = 0.
self.average = None
self.length = 0
self._first_link = None
def add_link(self,val):
new_link = Link(val)
new_link.next = self.current_link
self.current_link = new_link
if self._first_link is None:
self._first_link = self.current_link
self.sum += val
if self.length < self.maxlength:
self.length += 1
else:
self.sum -= self._first_link.value
self._first_link = self._first_link.next # this line is flawed
self.average = self.sum/self.length
def get_first(self):
return self._first_link.value
# Main
ll = LinkedList(5)
for ii in xrange(10):
ll.add_link(ii)
print ii,ll.get_first(),ll.average
The problem is that _first_link gets set to a value that doesn’t have a next. That is, _first_link gets set to the first item that's added, but its next is None, so I don't see how to move it along by 1 as I want to. This is what makes me wonder if a doubly linked list is needed.
I'd appreciate any advice.
I think the simplest implementation is to use a circular linked list (a.k.a. a ring):
class Link(object):
def __init__(self, value=0.0):
self.next = None
self.value = value
class LinkedRing(object):
def __init__(self, length):
self.sum = 0.0
self.length = length
self.current = Link()
# Initialize all the nodes:
last = self.current
for i in xrange(length-1): # one link is already created
last.next = Link()
last = last.next
last.next = self.current # close the ring
def add_val(self, val):
self.sum -= current.value
self.sum += val
self.current.value = val
self.current = self.current.next
def average(self):
return self.sum / self.length
# Test example:
rolling_sum = LinkedRing(5)
while True:
x = float(raw_input())
rolling_sum.add_val(x)
print(">> Average: %f" % rolling_sum.average())
You can implement this using collections.deque and the numerically stable math for maintaining running averages:
import collections
class AveragingBuffer(object):
def __init__(self, maxlen):
assert( maxlen>1)
self.q=collections.deque(maxlen=maxlen)
self.xbar=0.0
def append(self, x):
if len(self.q)==self.q.maxlen:
# remove first item, update running average
d=self.q.popleft()
self.xbar=self.xbar+(self.xbar-d)/float(len(self.q))
# append new item, update running average
self.q.append(x)
self.xbar=self.xbar+(x-self.xbar)/float(len(self.q))
if __name__=="__main__":
import scipy
ab=AveragingBuffer(10)
for i in xrange(32):
ab.append(scipy.rand())
print ab.xbar, scipy.average(ab.q), len(ab.q)
Okay, I thought of a solution that works in O[1] time. I'm still curious if anyone has a linked-list-based solution, but this solution avoids the LL entirely:
class Recent:
def __init__(self,maxlength):
self.maxlength = maxlength
self.length = 0
self.values = [0 for ii in xrange(maxlength)]
self.index = 0
self.total = 0.
self.average = 0.
def add_val(self,val):
last = self.values[self.index%self.maxlength]
self.values[self.index%self.maxlength] = val
self.total += val
self.total -= last
if self.length < self.maxlength:
self.length += 1
self.average = self.total / self.length
self.index += 1
def print_vals(self):
print ""
for ii in xrange(self.length):
print ii,self.values[ii%self.maxlength]
print "average:",self.average
# Example to show it works
rr = Recent(5)
for ii in xrange(3):
rr.add_val(ii)
rr.print_vals()
for ii in xrange(13):
rr.add_val(ii)
rr.print_vals()

Categories

Resources