How can I find the smallest leaf node in min Heap using heap operations only?
If it is a binary heap you can take [floor(n/2)]+1 when n is the number of elements on the heap It would give you the left most leaf node.
The only requirement in the min heap is that each node is smaller than its parent. Thus, there is no order between leaves, which means that such leaf can be any node among the second half of the array which is used to store the heap. So, one should traverse n/2 elements (second half of the array) and find the smallest one.
Related
Let's say we're given with a MAX Heap and we want to delete any of the leaf node, then how much time will it take to delete any of the leaf node and maintain the max heap property?
My main doubt is - will it O(n) time to reach to leaf nodes?
Also, why Binary Heaps has to be a complete Binary Tree and not almost complete Binary tree?
A binary heap is a complete binary tree. All levels are full, except possibly the last, which is left-filled. A binary tree is not necessarily a full binary tree.
In a binary heap of size N, represented in an array, the leaf nodes are in the last half of the array. That is, the nodes from N/2 to N-1 are leaf nodes. Deleting the last node (i.e. a[N-1]) is an O(1) operation: all you have to do is remove the node and decrease the size of the heap.
Removing any other leaf node is potentially an O(log n) operation because you have to:
Move the last node, a[N-1] to the node that you're deleting.
Bubble that item up into the heap, to its proper position.
The first part is, of course, O(1). The second part can require up to log(n) - 1 moves. The average is less than 2, but the worst case is log(n) - 1.
In a MAX heap you can access the leaf node in the heap in O(logn) as it is a complete binary tree and traversing the entire height of the tree takes O(logn)
Once this is done, you can call heapify to build the heap again which takes O(logn)
Almost Complete Binary Tree is no different from Complete Binary Tree except that it has following two restrictions :
At every node after completion of current level only go to next level.
At every node after completion of left node go to right.
Every formula that is applicable to complete binary tree will be applicable to almost complete binary tree.
The only difference is there is a gap at last level from right to left in almost complete binary tree. If there is no gap then it is Complete Binary Tree.
Heap is forced to have this property of being a compete binary tree for effciency purposes
We are given a tree with n nodes in form of a pointer to its root node, where each node contains a pointer to its parent, left child and right child, and also a key which is an integer. For each node v I want to add additional field v.bigger which should contain number of nodes with key bigger than v.key, that are in a subtree rooted at v. Adding such a field to all nodes of a tree should take O(n log n) time in total.
I'm looking for any hints that would allow me to solve this problem. I tried several heuristics - for example when thinking about doing this problem in bottom-up manner, for a fixed node v, v.left and v.right could provide v with some kind of set (balanced BST?) with operation bigger(x), which for a given x returns a number of elements bigger than x in that set in logarihmic time. The problem is, we would need to merge such sets in O(log n), so this seems as a no-go, as I don't know any ordered set like data structure which supports quick merging.
I also thought about top-down approach - a node v adds one to some u.bigger for some node u if and only if u lies on a simple path to the root and u<v. So v could update all such u's somehow, but I couldn't come up with any reasonable way of doing that...
So, what is the right way of thinking about this problem?
Perform depth-first search in given tree (starting from root node).
When any node is visited for the first time (coming from parent node), add its key to some order-statistics data structure (OSDS). At the same time query OSDS for number of keys larger than current key and initialize v.bigger with negated result of this query.
When any node is visited for the last time (coming from right child), query OSDS for number of keys larger than current key and add the result to v.bigger.
You could apply this algorithm to any rooted trees (not necessarily binary trees). And it does not necessarily need parent pointers (you could use DFS stack instead).
For OSDS you could use either augmented BST or Fenwick tree. In case of Fenwick tree you need to preprocess given tree so that values of the keys are compressed: just copy all the keys to an array, sort it, remove duplicates, then substitute keys by their indexes in this array.
Basic idea:
Using the bottom-up approach, each node will get two ordered lists of the values in the subtree from both sons and then find how many of them are bigger. When finished, pass the combined ordered list upwards.
Details:
Leaves:
Leaves obviously have v.bigger=0. The node above them creates a two item list of the values, updates itself and adds its own value to the list.
All other nodes:
Get both lists from sons and merge them in an ordered way. Since they are already sorted, this is O(number of nodes in subtree). During the merge you can also find how many nodes qualify the condition and get the value of v.bigger for the node.
Why is this O(n logn)?
Every node in the tree counts through the number of nodes in its subtree. This means the root counts all the nodes in the tree, the sons of the root each count (combined) the number of nodes in the tree (yes, yes, -1 for the root) and so on all nodes in the same height count together the number of nodes that are lower. This gives us that the number of nodes counted is number of nodes * height of the tree - which is O(n logn)
What if for each node we keep a separate binary search tree (BST) which consists of nodes of the subtree rooted at that node.
For a node v at level k, merging the two subtrees v.left and v.right which both have O(n/2^(k+1)) elements is O(n/2^k). After forming the BST for this node, we can find v.bigger in O(n/2^(k+1)) time by just counting the elements in the right (traditionally) subtree of the BST. Summing up, we have O(3*n/2^(k+1)) operations for a single node at level k. There are a total of 2^k many level k nodes, therefore we have O(2^k*3*n/2^(k+1)) which is simplified as O(n) (dropping the 3/2 constant). operations at level k. There are log(n) levels, hence we have O(n*log(n)) operations in total.
Is it possible to compute how many nodes have arbitrary binary tree? The leaf count and the depth of every leaf are known (it is Huffman tree actually).
I need it in order to be able to allocate needed memory for the tree before building it actually and to avoid memory re-allocations later.
A Huffman tree is a full binary tree, i.e. every node in the tree has either 0 or 2 children. In this case you need exactly k - 1 inner nodes for k leafs. So the total number of nodes is 2k - 1.
How can I go about proving that maximum item in a min-heap must be at one of the leaves, in a tree with N items?
I understand the overall design of a min-heap, and I can show/diagram that the maximum item is at one of the leaves (node at depth N + 1 > node at depth N). I'm just unsure as to how I should format the proof.
For start, please note that "heap" property requires that subtrees rooted at non-leaf nodes should also maintain the heap property because they are also heaps. For min-heap, the "heap" property is that root value should be less than values at the children.
If any non-leaf node of a min-heap holds the maximum item, then the heap property of the subtree whose root is the current non-leaf node is violated because children values of this subtree is less than the root value. To maintain the heap property, the root value has to be floated down to one of the children.
In order to not violate the "heap" property, the floating down of the "maximum" item will continue until the node holding the maximum value has no more children. Thus, the "maximum" item will always be at a node that has no children (i.e. leaf node).
To state the answer simply, assume for the sake of contradiction the max value is in a non-leaf. This violates the heap property, which for min-heaps requires that a node is smaller than its children in value. Therefore, the max value must be in a leaf.
I am implementing a min-max heap, a type of double-ended priority queue. You can look here here for more information about min-max heaps.
The code for insertion and delete-min operations are simple and available on the net. But, I am also trying to implement the delete-max operation on a min-max heap.
Initially, I felt that delete-max in min-max heap would be same as delete-max in max-min heap(if we consider the subtree of min-max heap containing the maximum element, it resembles a max-min heap). So, the implementation would be simple and analogous to delete-min of min-max heap.
But, there is a problem:
As can be seen in the above figure, though 70 is the max element, the last element(12) of the min-max heap is not in the subtree containing 70. So, can I use it to replace the gap left in left subtree after deletion of 70?
If we don't use that element and instead follow delete-max procedure of max-min heap and use 20 to replace the gap, the next element inserted in the heap will be at right child of 10 and forever there will be no right child of 9.
So, can anyone help me?
I believe that it is correct to remove the rightmost node on the last level and use it to replace the max element that was removed, even if it crosses in the tree. The rationale is the following:
Removing the rightmost node in the last level does not change any of the invariants that need to hold for any nodes within that tree: all of the nodes at min levels are still smaller than all of their descendants, and all of the nodes at max levels are still greater than their descendants.
The tree is still a complete binary tree.
Once you have moved this node over, you can then use the normal fixup procedure in a max-min heap in order to ensure that the left subtree invariants still hold.
Hope this helps!