问题
I understand the algorithm of building heap tree (max or min) but i don't understand the code of it:
First: How does this loop build a max heap?, why we started the i with n/2-1 ?
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
and this is the Heapify function:
Secondly: how did we assume that largest is "i" ?
Third: why we heapify again in the last line?
// To heapify a subtree rooted with node i which is
// an index in arr[]. n is size of heap
void heapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2*i + 1; // left = 2*i + 1
int r = 2*i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
// If largest is not root
if (largest != i)
{
swap(arr[i], arr[largest]);
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
The code and the algorithm i got,is from GeeksForGeeks
回答1:
Let's do this with a very simple example of building a max heap, which I think will answer your questions. Imagine you have the array [3, 1, 6, 4, 7, 9]
. That corresponds to this binary tree:
3
1 6
4 7 9
The idea of the algorithm is to push things down the heap to their proper place. Your first question is why we start at i = n//2
. The simple answer is that any node at position greater than i//2 is a leaf; it has no children and therefore cannot be pushed down. Actually, we can start at (n-1)//2
, because if n
is even then the first non-leaf node is there, and for an odd number, (n-1)//2 == n/2
.
So in this case, i=2
. Your next question is why we assume that the element at index i
is the largest. We don't. We start with that, because we have to find the largest of the three items (the item at i
and its two children). So we just default to i
. You could, if you want, set largest
to the left child, and then do the comparisons. But there's no particular reason to do it that way. You have to start with something, and the item at index i
is the easiest.
In this case, the item at index i
is 6. We examine the item's children and find that 9 is larger, so we swap. The result is:
3
1 9
4 7 6
We decrement i
, giving us i=1
. Looking at the item there and its children, we see that 7 is the largest, so we swap the two items, giving:
3
7 9
4 1 6
And now we're at the root. 9 is the largest among the root and its children, so we swap:
9
7 3
4 1 6
And here's the answer to your third question: why the recursive call to heapify
? You have to push the item down the heap as far as it will go. Here, 3 is smaller than 6, so we have to swap those items to give:
9
7 6
4 1 3
回答2:
1) Consider heap structure
M
K L
G H I J
A B C D E F
Last level contains at most half of all items ((n+1)//2
), so item at index n/2-1
always is parent of the last items at the last level. And starting from that index and traversing left we are ordering three-items mini-heaps, then traversing up and left we are ordering 7-items heaps, ans so on.
2) It is simple initialization of conditional task - if we find larger descendant, it replaces parent
3) If parent has been replaced, it moved down, and might be smaller than new decendants, so we must check (small element sinks down)
回答3:
The largest child index ci
of a parent node is:
ci = 2*i + 2 < size
i < (size - 2)/2
i < size/2 - 1
but you need to include size/2 - 1
, as a node may have just one child and i
goes all the way to zero, as all those nodes are parent nodes. As for recursion, you need to enforce the max-heap rule after a swap.
来源:https://stackoverflow.com/questions/52600839/how-to-build-heap-tree