I scoured the web to come up with this implementation of MinHeap and Maxheap in Python.
import heapq
class MinHeap:
def __init__(self):
self.heap = []
def push(self, item):
heapq.heappush(self.heap, item)
def pop(self):
return heapq.heappop(self.h)
def __getitem__(self, item):
return self.heap[item]
def __len__(self):
return len(self.h)
class MaxHeap(MinHeap):
def push(self, item):
heapq.heappush(self.heap, Comparator(item))
def pop(self):
return heapq.heappop(self.h)
def __getitem__(self, i):
return self.heap[i].val
class Comparator:
def __init__(self, val):
self.val = val
def __lt__(self, other):
return self.val > self.other
def __eq__(self, other):
return self.val == self.other
def __str__(self):
return str(self.val)
Now I need to add a peek method to both these classes. In it's current implementation I could pop and push back. But my question is, is there a better way to do it. Something in O(1) time.
These classes are based on Python's heapq structure, which is built on a standard Python list. The smallest item in the minheap and the largest item in the maxheap is at index zero. So just return
self.heap[0]
If the heap is empty, that will cause an error, but that probably is what you want.
Related
I would like to have a Python #cache decorator based on identity, not __hash__/__equal.
That is to say, I would like the cached value for an argument ka NOT to be used for a different object ka2, even if ka == ka2.
Is there a way to do that?
In code:
from functools import cache
class Key:
def __init__(self, value):
self.value = value
def __eq__(self, another):
print(f"__eq__ {self.value}, {another.value}")
return another.value == self.value
def __hash__(self):
print(f"__hash__ {self.value}")
return hash(self.value)
def __repr__(self):
return self.value
i = 0
#cache
def foo(key):
global i
i += 1
print(f"Computing foo({key}) = {i}")
return i
ka = Key('a')
ka2 = Key('a')
print(f"foo(ka): {foo(ka)}")
print(f"foo(ka2): {foo(ka2)}") # I would like the cached value for ka NOT to be used even though ka2 == ka.
Make a wrapper like Key that compares by the identity of its wrapped object, and wrap your caching function in a helper that uses the wrapper:
class Id:
__slots__="x",
def __init__(self,x): self.x=x
def __hash__(self): return id(self.x)
def __eq__(self,o): return self.x is o.x
def cache_id(f):
#functools.cache
def id_f(i): return f(i.x)
#functools.wraps(f)
def call(x): return id_f(Id(x))
return call
#cache_id
def foo(key): …
I am currently learning python. I am learning about classes, inheritance, and abstract classes. Here is the constructor in question:
def __init__(self, sourceCollection = None):
"""Sets the initial state of self, which includes the
contents of sourceCollection, if it's present."""
self.size = 0
if sourceCollection:
for item in sourceCollection:
self.add(item)
I am getting the following error, and I don't know why:
TypeError: 'int' object is not iterable
In case is helps, here is my add method:
def add(self, item):
"""Adds item to self."""
# Check array memory here and increase it if necessary
self.items[len(self)] = item
self.size += 1
Could anyone assist me with why I am getting this error? I did some research, but to no avail. Thanks so much in advance!!!
list has a method to add all elements from an iterable
Don't use self.size to keep track of the number of elements in self.items, use len(self.items)
def __init__(self, sourceCollection = None):
"""Make a copy of sourceCollection"""
self.items = []
if not sourceCollection: return
self.items.extend(sourceCollection)
def add(self, item):
"""Adds item to self."""
self.items.append(item)
#property
def size(self):
return len(self.items)
Just do (.append()):
def add(self, item):
"""Adds item to self."""
# Check array memory here and increase it if necessary
self.items.append(item)
self.size += 1
I'm reading a book on data structures and algorithms and understand the overall goal of the code but for top() and pop() there are strange member variables. Is this some sort of python abstraction that I am running into (ex. self._head._element) or a feature of not using pythons dictionary variable assignment?
'''
class LinkedStack:
class _Node:
__slots__ = '_element','_next' #treats elements not like a dictionary
def __init__(self, element, next):
self._element = element
self._next = next
def __init__(self):
self._head = None
self._size = 0
def __len__(self):
return self._size
def is_empty(self):
return self._size == 0
def push(self, e):
self._head = self._Node(e, self._head)
self._size += 1
def top(self):
if self.is_empty():
raise Empty('Stack is empty')
else:
return self._head._element
def pop(self):
if self.is_empty():
raise Empty('Stack is empty')
answer = self._head._element
self._head = self._head._next
self._size -=1
return answer
'''
I needed a dynamic size queue so I inherited list and Iterable and I tested all the stuff like appending, indexing and iterating but there is a small problem. Methods like
str(DataSet) return an empty list, and the Python debugger does show an empty list, which is expected, since I don't append to the list parent but the internal data. What do I need to override to not return self but return self.data?
class DataSet(collections.Iterable, list):
data = collections.deque()
index = 0
max = 3
def __add__(self, other):
self.append(other)
def append(self, item):
if len(self.data) >= self.max:
self.data.popleft()
self.data.append(item)
def __next__(self):
if self.index < len(self.data):
ret = self.data[self.index]
self.index += 1
return ret
raise StopIteration
def __getitem__(self, i):
return self.data[i]
def __iter__(self):
self.index = 0
return self
def setMax(self, max):
self.max = max
def __len__(self):
return len(self.data)
Override
def __str__(self):
return str(self.data)
I need to mirror a queue using a function called mirror
I have made the code for the queue class, but i dont know how to create a mirror of it. It needs to print out the original queue and then the same queue reversed
Any help would be appreciated
My Code:
class Queue:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def enqueue(self, item):
self.items.insert(0,item)
def dequeue(self):
return self.items.pop()
def is_empty(self):
return not self.items
def size(self):
return len(self.items)
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
def mirror(n):
pass
This will work. Your queue is composed of a list, so you can use slice syntax on the list to get a reversed version of the queue.
class Queue:
def __init__(self):
self.items = []
def enqueue(self, item):
self.items.append(item)
def __str__(self):
'''Allow print to be called on the queue object itself'''
return str(self.items)
def __getitem__(self, i):
'''Allow the queue object to be indexable directly'''
return self.items[i]
def mirror(q):
return q[::-1]
q = Queue()
for i in range(10):
q.enqueue(i)
print q
print mirror(q)
Note: A queue appends to the end, not the start. That's the behaviour of a stack.
Maybe you give this one a try: How can I reverse a list in python
You can create a new queue using the reversed self.items list in a member function mirror.
q = ArrayQueue()
def mirror(q):
copy = ArrayQueue()
stack = ArrayStack()
while not q.is_empty():
stack.push(q.first())
copy.enqueue(q.dequeue())
while not stack.is_empty():
copy.enqueue(stack.pop())
for i in range(len(copy)):
print(copy.dequeue(),end=" ")