I tried writing an algorithm that prints the k largest elemtns of a max heap but I cannot do it in the right complexity.
This is the Pseudo-code I wrote-
Print_k_largest(A[1,…,n],k):
If k>Heapsize(A):Error
i=1
insert[B,A[i])
print(B[1])
k-=1
While k>0:
if 2*i< Heapsize(A):
Insert(B,A[2*i])
Insert(B,A[2*i+1])
elif 2*i= Heapsize(A):
Insert(B,A[2*i])
B[1]=B[Heapsize(B)]
Heapsize(B)-=1
Max-Heapify(B,1)
print(B[1])
i=Binary_search(A[1,…,n],B[1])
k-=1
In this solution I create a new max heap based on the original one, so that its size is always smaller than K hence the complexity of max-heapify and other such functions is O(klogk) and not O(klogN) as I was requested to do. This Pseudocode is based on the solution suggested here.
The idea is like this- because it's a max heap the largest element is the root, the second largest element is one of the root's son, the third one is either the other son or the sons of the current largest one and so on. In each iteration I insert the sons of the former largest (the one I printed before), remove the former largest, Max-heapify (to make the heap a max heap again, hence the root is the newest largest) and print the newest largest (newest root). The principle in this brilliant solution (unfortuantely not mine haha) is to do all the changes on a second heap whose size is always smaller than K (because in each of the k iterations we add maximum 2 new elements and remove one) so that the runtime for actions like max-heapify is O(logk) and not O(logn). The thing is that to add the sons of the current largest I need an acess to its location (index) on the original tree! I don't know how to do it without it costing logn and runing everything.
I would appreaciate any help.
(This might be exactly the algorithm you're already trying to implement, if so hope this phrasing makes it clearer)
So I would create a second heap, but it would not just be a heap of values - it would be a heap of positions in the original heap, inserted by the value at that position.
Call the original heap
A
and the new heapB
. Start by inserting the head ofA
intoB
. Then, repeatedly pop the head ofB
, and insert the children (inA
) into B.So if
A
is build out of nodes like:Ordered by
value
Then
B
will be build out of meta-Nodes like:Ordered by
value.value
Initialize B with
MetaNode(A.head)
as its only elementThen repeatedly do:
That isn't the simplest algorithm I've ever described, so if anything is unclear, please ask and I'll try to describe it more clearly. :)