Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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.