I'm trying to figure out how I can initialize a min heap using an array. So far my function looks like this:
def start_heap(self,n):
# None positions to be filled with Nodes
arr = [none][] * n
for i in arr:
heapify(i)
def heapify(self):
start = self.parent(len(self) - 1) # Start at parent of last leaf
for j in range(start, -1, -1): # going to and including the root.
self.heapify_down(j)
def heapify_down(self, i):
n = len(self._pq)
left, right = self.left(i), self.right(i)
if left < n:
child = left
if right < n and self.pq[right] < self.pq[left]:
child = right
if self.pq[child] < self.pq[i]:
self.swap(i, child)
self.heapify_down(child)
Heapify Down Pseudocode:
Heapify-down(H,i): Let n = length(H) If 2i>n then
Terminate with H unchanged Else if 2i<n then
Let left=2i, and right=2i+1
Let j be the index that minimizes key[H[left]] and key[H[right]] Else if 2i=n then
Let j=2i Endif
If key[H[j]] < key[H[i]] then
swap the array entries H[i] and H[j] Heapify-down(H , j)
Endif
I'm going to build a simple node class that just holds data but I'm not sure how to actually get the start_heap function working. Keep in mind n is the maximum number of elements that can be stored.
Some remarks on the code you provided (not on the code you didn't provide):
arr is a local variable, so whatever you do with it, once the function returns, that arr will be out of scope... and lost. You need an attribute or else subclass list
It is not common practice to "allocate" the array and fill it with None. In Python lists are dynamic, so you don't need to reserve slots ahead of time. You just need an empty list to start with.
There is no need to call heapify when the heap is empty.
There is certainly no need to call heapify many times in a loop. All the logic for heapifying is already present in that method, so no need to call it on each index individually. But as stated in the previous point: no need to call it on an empty list -- there is nothing to move.
So the correction is quite basic:
def start_heap(self, max_size):
self.max_size = max_size
self._pq = []
Then, in many of your other methods, you will have to work with self._pq and self.max_size.
For instance, it could have a method that indicates whether the heap is full:
def is_full(self):
return len(self._pq) >= self.max_size
If you have an add method, it would first check if there is still room:
def add(self, node):
if is_full(self):
raise ValueError("Cannot add value to the heap: it is full")
# ... rest of your code ...
Related
While practicing for my final in Python programming I ran into this question "def rotaten" of rotating k times. The problem says that k can range from 0 to any positive integer number (even greater than list size, if k < 0 raise ValueError
and it must execute in O( (n-k)%n ) where n is the length of the list. It also has the following warnings:
WARNING: DO NOT call .rotate() k times !!!!
WARNING: DO NOT try to convert whole linked list to a python list
WARNING: DO NOT swap node data or create nodes
The problem is that I'm not understanding the solution given. Is there an easier way to solve this problem? Thank you in advance
class Node:
def __init__(self,initdata):
self._data = initdata
self._next = None
def get_data(self):
return self._data
def get_next(self):
return self._next
def set_data(self,newdata):
self._data = newdata
def set_next(self,newnext):
self._next = newnext
class LinkedList:
def rotaten(self, k):
if k < 0:
raise ValueError
if self._size > 1:
m = k % self._size
if m > 0 and m < self._size:
current = self._head
for i in range(self._size - m - 1):
current = current.get_next()
chain_b = current.get_next()
old_head = self._head
old_last = self._last
self._last = current
self._last.set_next(None)
self._head = chain_b
old_last.set_next(old_head)
The easiest ways are forbidden
warning forbids implementing the singular rotation, then calling it repeatedly
warning forbids using native python structure - python has list built-in in basic collections list(), which can be then transformed to a deque, which can then be rotated by popping from the end and inserting the same node to the beginning.
warning is preventing you from making your life easier by creating some other nodes or worse - copying data. (copying data from one node to another would remove any advantage you had from storing the data into the lists in the first place)
The example solution is basically this:
Take the current first node(head of the list) and the tail node which is stored in the List structure. (the bookkeeping of the example list consists of holding the head and tail, the rest is done in the nodes themselves)
Find the k-th node - so that you rotate the whole list at once. This is where the list needs to be cut.
Add the last node as the new head, doing all the necessary reference-linking and unlinking. (Which is I guess the point of this question - to test if you understand the references. In C these would be pointers, python has the references implicitly.)
So as far as the linked lists go, this is the most straightforward solution with the requested O((n-k)%n) complexity.
Good luck with your pointers :-).
I have an unknown number of Integer variables say that can range from [0,9]
I want to iterate over all permutations of these values.
If the number of variables was constant, it would be easy to write nested for loops. I came up with a recursive function that does what I want, but was curious if there was a way to do it iteratively.
def nested(array,index):
n = len(array)
for i in range(10):
array[n-index]=i
#len(array-1) end of array
if(index == 1):
print(array)
#do something later
else:
nested(array,index-1)
#generate all permutations, change n to change size of list.
n = 4
array = [0]*n
nested(array,len(array))
I tried using the so called "Simple Method" found here -> http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html
But I couldn't get it to work.
As was mentioned by another commenter, the key is to simulate your tail recursion using a stack.
Take note I append() a tuple of (array, index) into the stack, which mirrors the call to recursive function in your original recursive solution. At the start of the iteration, it does stack.pop(), which mimics the body of your recursive function. Recursive call becomes stack.append().
def nested(array):
stack = []
n = len(array)
stack.append((array.copy(), n))
while(stack):
array, index = stack.pop()
for i in range(10):
array[n-index]=i
#len(array-1) end of array
if(index == 1):
print(array)
#do something later
else:
stack.append((array.copy(), index-1))
#generate all permutations, change n to change size of list.
n = 4
array = [0]*n
nested(array)
Please refer to itertools. There is a Class "permutations" that could solve your problem perfectly.
I've written the following code for HeapSort, which is working fine:
class Heap(object):
def __init__(self, a):
self.a = a
def heapify(self, pos):
left = 2*pos + 1
right = 2*pos + 2
maximum = pos
if left < len(self.a) and self.a[left] > self.a[maximum]:
maximum = left
if right < len(self.a) and self.a[right] > self.a[maximum]:
maximum = right
if maximum != pos:
self.a[pos], self.a[maximum] = self.a[maximum], self.a[pos]
self.heapify(maximum)
def buildHeap(self):
for i in range(len(self.a)/2, -1, -1):
self.heapify(i)
def heapSort(self):
elements = len(self.a)
for i in range(elements):
print self.a[0]
self.a[0] = self.a[-1]
self.a = self.a[:-1]
self.heapify(0)
def printHeap(self):
print self.a
if __name__ == '__main__':
h = Heap(range(10))
h.buildHeap()
h.printHeap()
h.heapSort()
However, it seems that the function heapSort here will take time O(n^2), due to list slicing. (For a list of size 'n', slicing it to 'n-1' will take O(n-1) time).
Can anyone confirm if my thinking is correct over here ?
If yes, what should be the minimal change in heapSort function to make it run in O(nlogn) ?
Yes, I believe you are correct. To make it faster, replace things like this:
self.a = self.a[:-1]
with:
self.a.pop()
The pop() member function of lists removes and returns the last element in the list, with constant time complexity.
lists are stored as contiguous memory, meaning all the elements of a list are stored one after the other. This is why inserting an element in the middle of a list is so expensive: Python has to shift all the elements after the place you're inserting in down by one, to make space for the new element. However, to simply delete the element at the end of list takes negligible time, as Python merely has to erase that element.
I am having real trouble using my custom-made heap class functions to be used in my Priority Queue class. I am having trouble on what functions from my heap class to use for my "enqueue", "dequeue", "front" and "size" functions for my PriorityQueue. I know for "enqueue" I need to use my insert function, but I don't know how to go about this because I have a priority. Could someone help me out what I need to do in order to make my PriorityQueue class to use the functions from my Heap class in order to work properly? I have been stuck on this for awhile and I keep finding answers that include using the built in python functions such as queue and heapq.
class Heap(object):
def __init__(self, items=None):
'''Post: A heap is created with specified items.'''
self.heap = [None]
if items is None:
self.heap_size = 0
else:
self.heap += items
self.heap_size = len(items)
self._build_heap()
def size(self):
'''Post: Returns the number of items in the heap.'''
return self.heap_size
def _heapify(self, position):
'''Pre: Items from 0 to position - 1 satisfy the Heap property.
Post: Heap Property is satisfied for the entire heap.'''
item = self.heap[position]
while position * 2 <= self.heap_size:
child = position * 2
# If the right child, determine the maximum of two children.
if (child != self.heap_size and self.heap[child+1] > self.heap[child]):
child += 1
if self.heap[child] > item:
self.heap[position] = self.heap[child]
position = child
else:
break
self.heap[position] = item
def delete_max(self):
'''Pre: Heap property is satisfied
Post: Maximum element in heap is removed and returned. '''
if self.heap_size > 0:
max_item = self.heap[1]
self.heap[1] = self.heap[self.heap_size]
self.heap_size -= 1
self.heap.pop()
if self.heap_size > 0:
self._heapify(1)
return max_item
def insert(self, item):
'''Pre: Heap Property is Satisfied.
Post: Item is inserted in proper location in heap.'''
self.heap_size += 1
# extend the length of the list.
self.heap.append(None)
position = self.heap_size
parent = position // 2
while parent > 0 and self.heap[parent] < item:
# Move the item down.
self.heap[position] = self.heap[parent]
position = parent
parent = position // 2
# Puts the new item in the correct spot.
self.heap[position] = item
def _build_heap(self):
''' Pre: Self.heap has values in 1 to self.heap_size
Post: Heap property is satisfied for entire heap. '''
# 1 through self.heap_size.
for i in range(self.heap_size // 2, 0, -1): # Stops at 1.
self._heapify(i)
def heapsort(self):
'''Pre: Heap Property is satisfied.
Post: Items are sorted in self.heap[1:self.sorted_size].'''
sorted_size = self.heap_size
for i in range(0, sorted_size -1):
# Since delete_max calls pop to remove an item, we need to append a dummy value to avoid an illegal index.
self.heap.append(None)
item = self.delete_max()
self.heap[sorted_size - i] = item
So this is working but like I previously stated I am having trouble on how to make a priority queue out of this? I know asking for code is wrong, but I'm desperate could anyone help me out here? I have the basic rundown on what I want my priority code to do..
#PriorityQueue.py
from MyHeap import Heap
class PriorityQueue(object):
def __init__(self):
self.heap = None
def enqueue(self, item, priority):
'''Post: Item is inserted with specified priority in the PQ.'''
self.heap.insert((priority, item))
def first(self):
'''Post: Returns but does not remove the highest priority item from the PQ.'''
return self.heap[0]
def dequeue(self):
'''Post: Removes and returns the highest priority item from the PQ.'''
if self.heap is None:
raise ValueError("This queue is empty.")
self.heap.delete_max()
def size(self):
'''Post: Returns the number of items in the PQ.'''
return self.size
This is what I got so far but I do not know if it is entirely correct. Could anyone help me out?
I edited my code to the most current version of it.
Since this is presumably homework, all I can do is give hints, which is often easier done as comments. Since this ended up being a fairly thorough series of hints I'm summarizing them as an answer here.
For the most part, methods in your PriorityQueue class will map to methods you've already implemented in your Heap class:
PriorityQueue.enqueue() maps pretty easily to Heap.insert()
PriorityQueue.first() does not have a corresponding heap method, but can still be implemented in one line. You just need to return the maximum value, which will always be at a specific place in your heap.
PriorityQueue.dequeue() is a little more complicated. It needs to save the value of the top item first so that it can return it after calling heap.delete_max()
The heap class already has a size() method, which PriorityQueue.size() can call, instead of maintaining a separate size variable within the PriorityQueue class.
Additionally, you need an init function, This should create a new Heap object that will be maintained by the class.
In order to make an iterator, you'll need to make a new class. It will need to maintain an integer variable (let's call it self.index), indicating its current place in the queue. You'll also want a method that increases self.index and returns the value that was at the previous index location. That should be about it.
I'm coding a O(n) algorithm of 'heapifying' a list in Python. I can't understand why it's not working.
def func(l):
size=len(l)
for root in range((size//2)-1,-1,-1):
child = 2*root+1 #parent of child is target
while(child<size):
#l[child] should be smaller sibling
if child<size-1 and l[child]>l[child+1]:
child+=1
#can we put l[root] in l[child//2]?
if l[root]<=l[child]:
break #yes
#no
l[child//2]=l[child]#move child up
child=2*child+1#move down a level
l[child//2]=l[root]
return l
There are two issues with your function.
The first is quite simple to grasp. You're using the wrong calculation to find the parent of your child index. Rather than child // 2, you should be using (child - 1) // 2. This was causing you to shift some values into the wrong spots.
The second issue is a bit more subtle. If l[root] is larger than one of its children, you're currently overwriting it with that child, and so when you try to insert it in another place later in the list, the original value is no longer available. Probably you should save l[root] at the top of the for loop, then use the saved value any time you're currently examining l[root] later in the code (the if inside the while loop and the final assignment after it ends.
Here's a fixed version of the code, with comments to point out the changes I made:
def func(l):
size=len(l)
for root in range((size//2)-1,-1,-1):
root_val = l[root] # save root value
child = 2*root+1
while(child<size):
if child<size-1 and l[child]>l[child+1]:
child+=1
if root_val<=l[child]: # compare against saved root value
break
l[(child-1)//2]=l[child] # find child's parent's index correctly
child=2*child+1
l[(child-1)//2]=root_val # here too, and assign saved root value
return l
Nice explanation above, here is a little revised version:
# heapify in place
def heapify(A):
# write your code here
for root in xrange(len(A)//2 - 1, -1, -1):
rootVal = A[root]
child = 2 * root + 1
while child < len(A):
if child+1 < len(A) and A[child] > A[child + 1]:
child += 1
if rootVal <= A[child]:
break
A[child], A[(child - 1)//2] = A[(child - 1)//2], A[child]
child = child * 2 + 1