Download Binary Heap

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Linked list wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Quadtree wikipedia , lookup

Red–black tree wikipedia , lookup

B-tree wikipedia , lookup

Interval tree wikipedia , lookup

Binary tree wikipedia , lookup

Binary search tree wikipedia , lookup

Transcript
Heap
https://en.wikipedia.org/wiki/Heap_%28data_structure%29
In computer science, a heap is a specialized tree-based abstract data type that satisfies the heap property:
If A is a parent node of B then the key of node A is ordered with respect to the key of node B with the
same ordering applying across the heap. Heaps can be classified further as either a "max heap" or a "min
heap". In a max heap, the keys of parent nodes are always greater than or equal to those of the children
and the highest key is in the root node. In a min heap, the keys of parent nodes are less than or equal to
those of the children and the lowest key is in the root node. Heaps are crucial in several efficient graph
algorithms such as Dijkstra's algorithm, and in the sorting algorithm heapsort. A common implementation
of a heap is the binary heap, in which the tree is a complete binary tree (see figure).
In a heap, the highest (or lowest) priority element is always stored at the root, hence the name heap. A
heap is not a sorted structure and can be regarded as partially ordered. As visible from the Heap-diagram,
there is no particular relationship among nodes on any given level, even among the siblings. When a heap
is a complete binary tree, it has a smallest possible height—a heap with N nodes always has log N height.
A heap is a useful data structure when you need to remove the object with the highest (or lowest) priority.
Note that, as shown in the graphic, there is no implied ordering between siblings or cousins and no implied
sequence for an in-order traversal (as there would be in, e.g., a binary search tree). The heap relation
mentioned above applies only between nodes and their parents, grandparents, etc. The maximum
number of children each node can have depends on the type of heap, but in many types it is at most two,
which is known as a binary heap.
The heap is one maximally efficient implementation of an abstract data type called a priority queue, and
in fact priority queues are often referred to as "heaps", regardless of how they may be implemented. Note
that despite the similarity of the name "heap" to "stack" and "queue", the latter two are abstract data
types, while a heap is a specific data structure, and "priority queue" is the proper term for the abstract
data type.
A heap data structure should not be confused with the heap which is a common name for the pool of
memory from which dynamically allocated memory is allocated. The term was originally used only for the
data structure.
Binary Heap
https://en.wikipedia.org/wiki/Binary_heap
A binary heap is a heap data structure created using a binary tree. It can be seen as a binary tree with two
additional constraints:


Shape property
A binary heap is a complete binary tree; that is, all levels of the tree, except possibly the last one
(deepest) are fully filled, and, if the last level of the tree is not complete, the nodes of that level
are filled from left to right.
Heap property
All nodes are either greater than or equal to or less than or equal to each of its children,
according to a comparison predicate defined for the heap.
Heaps with a mathematical "greater than or equal to" (≥) comparison predicate are called max-heaps;
those with a mathematical "less than or equal to" (≤) comparison predicate are called min-heaps. Minheaps are often used to implement priority queues.
Since the ordering of siblings in a heap is not specified by the heap property, a single node's two children
can be freely interchanged unless doing so violates the shape property (compare with treap). Note,
however, that in the common array-based heap, simply swapping the children might also necessitate
moving the children's sub-tree nodes to retain the heap property.
Insertion
https://en.wikipedia.org/wiki/Binary_heap
To add an element to a heap we must perform an up-heap operation (also known as bubble-up,
percolate-up, sift-up, trickle-up, heapify-up, or cascade-up), by following this algorithm:



Add the element to the bottom level of the heap.
Compare the added element with its parent; if they are in the correct order, stop.
If not, swap the element with its parent and return to the previous step.
The number of operations required is dependent on the number of levels the new element must rise to
satisfy the heap property, thus the insertion operation has a time complexity of O(log n). However, in
1974, Thomas Porter and Istvan Simon proved that the function for the average number of levels an
inserted node moves up is upper bounded by the constant 1.6067. The average number of operations
required for an insertion into a binary heap is 2.6067 since one additional comparison is made that does
not result in the inserted node moving up a level. Thus, on average, binary heap insertion has a constant,
O(1), time complexity. Intuitively, this makes sense since approximately 50% of the elements are leaves
and approximately 75% of the elements are in the bottom two levels, it is likely that the new element to
be inserted will only move a few levels upwards to maintain the heap.
As an example of binary heap insertion, say we have a max-heap
and we want to add the number 15 to the heap. We first place the 15 in the position marked by the X.
However, the heap property is violated since 15 > 8, so we need to swap the 15 and the 8. So, we have
the heap looking as follows after the first swap:
However the heap property is still violated since 15 > 11, so we need to swap again:
which is a valid max-heap. There is no need to check left child after this final step. Before we placed 15 on
X in 1-st step, the max-heap was valid, meaning 11 > 5. If 15 > 11, and 11 > 5, then 15 > 5, because of the
transitive relation.
Array Implementation
http://geeksquiz.com/binary-heap/
http://typeocaml.com/2015/03/12/heap-leftist-tree/
The array based implementation is actually beautiful. Essentially, it uses two tricks to simulate the binary
heap tree:


If the index of a root is i, then its left child index is 2*i+1 and right child index is 2*i+2.
The relationship of left child and right child is not important, so the two child slots in the array
for a root can be fully used.
class MinHeap
{
List<int> harr;
}
void insert(int k)
{
harr.Add(k);
int i = harr.Count - 1;
while (i != 0 && harr[parent(i)] > harr[i])
{
swap(i, parent(i));
i = parent(i);
}
}
int parent(int i) { return (i-1)/2; }
void swap(int i, int y)
{
int temp = harr[i];
harr[i] = harr[y];
harr[y] = temp;
}
Extract
https://en.wikipedia.org/wiki/Binary_heap
The procedure for deleting the root from the heap (effectively extracting the maximum element in a maxheap or the minimum element in a min-heap) and restoring the properties is called down-heap (also
known as bubble-down, percolate-down, sift-down, trickle down, heapify-down, cascade-down, boogiedown, and extract-min/max).



Replace the root of the heap with the last element on the last level.
Compare the new root with its children; if they are in the correct order, stop.
If not, swap the element with one of its children and return to the previous step. (Swap with its
smaller child in a min-heap and its larger child in a max-heap.)
So, if we have the same max-heap as before
We remove the 11 and replace it with the 4.
Now the heap property is violated since 8 is greater than 4. In this case, swapping the two elements, 4
and 8, is enough to restore the heap property and we need not swap elements further:
The downward-moving node is swapped with the larger of its children in a max-heap (in a min-heap it
would be swapped with its smaller child), until it satisfies the heap property in its new position. This
functionality is achieved by the Max-Heapify function as defined below in pseudocode for an array-backed
heap A of length heap_length[A]. Note that "A" is indexed starting at 1, not 0 as is common in many real
programming languages.
Max-Heapify (A, i):
left ← 2i
right ← 2i + 1
largest ← i
if left ≤ heap_length[A] and A[left] > A[largest] then:
largest ← left
if right ≤ heap_length[A] and A[right] > A[largest] then:
largest ← right
if largest ≠ i then:
swap A[i] ↔ A[largest]
Max-Heapify(A, largest)
For the above algorithm to correctly re-heapify the array, the node at index i and its two direct children
must violate the heap property. If they do not, the algorithm will fall through with no change to the
array. The down-heap operation (without the preceding swap) can also be used to modify the value of
the root, even when an element is not being deleted.
In the worst case, the new root has to be swapped with its child on each level until it reaches the
bottom level of the heap, meaning that the delete operation has a time complexity relative to the height
of the tree, or O(log n).
Array Implementation
http://geeksquiz.com/binary-heap/
int extractMin()
{
if (harr.Count == 0)
throws new Exception("Heap is empty");
if (harr.Count == 1)
{
int temp = harr[0]
harr.RemoveAt(0);
return temp;
}
int temp = harr[0];
harr[0] = harr[harr.Count - 1];
harr.RemoveAt(harr.Count – 1);
minHeapify(0);
return temp;
}
void minHeapify(int i)
{
int l = left(i);
int r = right(i);
int smallest = i;
if (l < harr.Count && harr[l] < harr[i])
smallest = l;
if (r < harr.Count && harr[r] < harr[smallest])
smallest = r;
if (smallest != i)
{
swap(i, smallest);
minHeapify(smallest);
}
}
int left(int i) { return (2*i + 1); }
int right(int i) { return (2*i + 2); }
Leftist Heap
https://en.wikipedia.org/wiki/Leftist_tree
http://typeocaml.com/2015/03/12/heap-leftist-tree/
In computer science, a leftist tree or leftist heap is a priority queue implemented with a variant of a binary
heap. Every node has an s-value which is the distance to the nearest leaf. In contrast to a binary heap, a
leftist tree attempts to be very unbalanced. In addition to the heap property, leftist trees are maintained
so the right descendant of each node has the lower s-value.
The height-biased leftist tree was invented by Clark Allan Crane. The name comes from the fact that the
left subtree is usually taller than the right subtree.
When inserting a new node into a tree, a new one-node tree is created and merged into the existing tree.
To delete a minimum item, we remove the root and the left and right sub-trees are then merged. Both
these operations take O(log n) time. For insertions, this is slower than binomial heaps which support
insertion in amortized constant time, O(1) and O(log n) worst-case.
Leftist trees are advantageous because of their ability to merge quickly, compared to binary heaps which
take O(n). In almost all cases, the merging of skew heaps has better performance. However merging leftist
heaps has worst-case O(log n) complexity while merging skew heaps has only amortized O(log n)
complexity.
Leftist tree always keeps the left branches of all roots being the longer and in worst case, they are as long
as the right branches. In other word, all right branches of all roots are shortest. This makes sense. When
we decide which branch to go, if we know one branch is always shorter than the other, then we should
take it. This is because shorter branch means potentially less nodes and the number of future possible
operations intends to be smaller.
In order to maintain this property, each node has a rank, which indidates the length of the path between
the node and the right most leaf. For example,
The way of keep ranks up-to-date is like this:




We always assume the rank of the right child <= the rank of the left child.
So we always go right.
If we reach a leaf, then we replace the leaf with our element and update the ranks of all the
parents back to the root. Note that the element in this context is not necessarily the original new
element which is being inserted and we will explain it soon.
When updating the rank of a parent, we first compare the rank of left rank_left and the rank
of right rank_right. If rank_left < rank_right, then we swap the left child and the right
child and update the rank of the parent to be rank_left + 1; other wise rank_right + 1
A diagram is better than hundreds of words. Let's build a leftist by inserting two elements.
We can see that by always putting the higher rank to the left can make the right branch being shortest all
the time. Actually, this strategy is how this design of tree based heap got the name leftist, i.e., more nodes
intend to be on the left side.
But this is not the full story of leftist. Actually, although the diagram above describes insert, it is just for
the purpose of demonstration of how ranks are updated.
In leftist tree, the most important operation is merge and an insert is just a merge with a singleton tree
that has only the new element and two leaves.
Merge is a recursive operation.




We have two trees to merge: merge t1 t2.
Compare two roots, if k1 > k2, we simply switch two trees by merge t2 t1. This is to make
sure the tree on the left always has smaller key, for conveniences.
Since t1 has smaller key, its root should stay as the new root.
Because t1's right branch r is always shortest, we then do merge r t2.


If one of the two trees is leaf, we simply returns the other. And begin the rank updating process
back to the root.
The rank updating is the same as we described in the previous section.
Again, let's see an example.