I'm prepping for a Google developer interview and have gotten stuck on a question about heaps. I need to implement a heap as a dynamic binary tree (not array) where each node has a pointer to the parent and two children and there is a global pointer to the root node. The book asks "why won't this be enough?"
How can the standard tree implementation be extended to support heap operations add() and deleteMin()? How can these operations be implemented in this data structure?
Can you keep the size of total nodes ? if so, it's easy to know where you should add new element, because that's an almost full tree.
About deleteMin, I think that it will be less effective because you can't access directly to all leaves, as in array (N/2).
You should travel through all paths till you get leaf and then compare them, probably it will cost O(n)
Related
I am currently learning data structure and trying to implement a BST and max-heap(use BST as base class). But I accidentally found it seems impossible to derive heap from BST. Almost all the implementation for heap are based on array rather then using pointers point to left and right, and most of BST are based on pointers rather than array.
So my question is why I have to use array to realize a heap? And, in realizing BST, why people choose to use pointers point to left and right rather array? I know use array to realize BST may cost more space, and it is harder to implement remove function, is there any more reason for that?
Thank you so much!
The main reason standard implementation of binary heaps is done using arrays is because heaps are complete binary trees.
Because complete binary trees always grow level by level(Meaning:First the parent level will be filled with nodes and only then the child level is filled).
Therefore,We are able to use arrays where for a node at position i, the left child is found at position 2*i and right child is found at position 2*i+1.
The reason that binary search trees is implemented using pointers and not using arrays is because binary search trees are not guaranteed to be complete binary trees
In a graph algorithm, I need to find the node with the smallest value.
In a step of the algorithm the value of this node or its neighbors can be decreased and a few of its neightbors can be removed dependent on their value.
Also, I don't want to search the whole graph for this node each time (although it is not so big (<1000 nodes)).
Therefore I looked at the STL library and found the heap structure which almost does what I want. I can insert and delete nodes very fast, but is there a method to update the heap fast when I only changed the value of one node without resorting the whole heap? I feel it would be a huge bottleneck in the program.
First the conceptual part:
If you use the heap insertion method with the element that decreased it's value as the starting point for insertion instead of starting at the back of the collection everything just works.
I haven't done that in C++ yet, but std::push_heap looks fine for that purpose.
Is it possible to traverse a tree structure (specifically an octree, the 3-D version of a binary tree) by using a fixed sized stack? I do not want to use recursion, since my octree is
quite deep.
I am traversing the tree to do a range search problem, to find all the points closest to a queried point. So in my traversal, I do not walk down those subtrees rooted at nodes which my search region does not intersect.
If your octree has parent pointers, I think you can traverse it without a stack at all (see this thread, for example). Without that, you will need a stack that is as deep as the depth of your tree, regardless of how many branches are skipped.
Of course you can traverse a tree without using a deep native call stack, using continuation passing style techniques, or (and this is grossly the same) by making a virtual machine, with its call stack implemented as a heap data, or (yet another point of view) by coding a stack automata with the stack implemented as an explicit heap data structure (e.g. a std::stack).
Think of it otherwise, your C++ naive code could run on a Turing machine, and these beasts don't have any stack.
As Ted Hopp's answer suggests, you might be inspired by Deutsch-Schorr-Waite's Garbage Collection techniques (with a few additional bits per node to temporarily flip the reference direction and remember that) to have a "stack-less" traversal (but you need additional bits in each node). But I believe that having your own stack inside a std::stack or std::vector is probably simpler.
Yes, you can traverse the octree with a fixed-size stack.
The fixed-size just needs to be as big as the longest possible octree depth.
Bear in mind that with an octree, each depth traversal can be recorded with only 3 bits of memory. For each of the three dimensions, you only need to record whether you went in a positive or negative direction.
So even if your octree goes 1000-deep, you can store the recursion with 375 bytes.
I found lots of MinMax Heap implementations, that were storing data in an array. It is realy easy to implement, that is way I am looking for something different. I want to create a MinMax Heap using only elements of the Heap with pointers to left child and right child (and afcourse a key to compare). So the Heap have only pointer to the root object (min level), and a root object have a pointer to his children (max level) and so on. I know how to insert a new object (finding a proper path by using binary represenation of int depending on Heap size), but I don't know how to implement the rest (push up (down) the element, find parent or grandparent).
Thx for help
A priority queue using a heap ordered binary tree can be implemented using a triply linked list structure instead of an array. you will need three links per node:two to traverse down and one to traverse up.
The heapq module source code shows to implement the steps for pushing up and down. To switch from an array implementation to a pointer implementation, replace the arr[2*n+1] computation with node.left and arr[2*n+2] with node.right. For parent references such as arr[(n-1)>>1], every node will need a pointer to its parent, node.parent.
Alternatively, you can adopt a functional style which makes this all very easy to implement. I found the code for treaps implemented in Lisp to be an inspiration for how to do this.
I have solved this problem as part of an assignment long back. You can find it here
I have multiple implementations in Java and C++ implementing MinHeap with and without arrays. See my Java implementations for the solution. And yes it is very much possible to implement Heap without arrays. You just have to remember where to insert the next node and how to heapify and reverse heapify.
Edit1: I also tried to look up any existing solutions for min heap without arrays but couldn't find any. So, I am posting it here so it could be helpful for anyone who wishes to know the approach.
Yes, you can implement it without relying on an array.
I personally relied on a binary counter...
Here is my implementation(https://github.com/mohamedadnane8/HeapsUsingPointers) in c.
Note that this is still a very fast implementation with log(n).
1 => binary "1"
2=> "10" 3=> "11"
4=> "100" 5= "101" 6="110" 7="111"
In this program i tried to use the sequence of numbers to insert and delete as u can see above the tree can be easily represented as binary strings of numbers.
The first '1' in the binary string is to start.
After that the sequence of 0 and 1 determines where to go '1' means go to the left and '0' go to the right.
Also, note that this implementation relies on a very small array of characters or integers that make the calculation of the binary numbers faster but u can rely on bin() function to convert ur counter to a binary number(I implemented the array just to practice a bit my problem-solving skills).
Sorry if I couldn't explain it very well, I lack a bit in my communication skills.
It is hard implement binary heap without array. Because you should keep all the parent while inserting you pass and then do operation push up and down. like that [parent_1, parent_2 ... parant_k] and then if parent_(k+1) < parant_k pushUp and rearrange their right child and left child
I have been implementing a heap in C++ using a vector. Since I have to access the children of a node (2n, 2n+1) easily, I had to start at index 1. Is it the right way? As per my implementation, there is always a dummy element at zeroth location.
Your way works. Alternatively you can have root at index 0 and have children at 2n+1 and 2n+2
While this works well for heaps, you end up using a huge amount of redundant memory for other tree data structures that do not necessarily have a full and complete Binary tree. For example, this means that if you have a Binary search tree of 20 nodes with a depth of 5, you end up having to use an array of 2^5=32 instead of 20. Now imagine if you need a tree of 25 nodes with a depth of 22. You end up using a huge array of 4194304, whereas you could have used a linked representation to store just the 25 nodes.
You can still use an array and not incur such a memory hit. Just allocate a large block of memory as an array and use array indices as pointers to the children.
Thus, where you had
node.left = (node.index*2)
node.right = (node.index*2+1)
You simply use
node.left = <index of left child>
node.right = <index of right child>
Or you can just use pointers/references instead of integer indices to an array if your language supports it.
Edit:
It might not be obvious to everyone that a complete binary search tree takes up O(2^d) memory. There are d levels and every level has twice as many nodes as the level its parent is in (because every node except those at the bottom has exactly two children - never one). A binary heap is a binary tree (but not a Binary Search Tree) that is always complete by definition, so an array based implementation outlined by the OP does not incur any real memory overhead. For a heap, that is the best way to implement it in code. OTOH, most other binary trees (esp. Binary Search Trees) are not guaranteed to be complete. So trying to use this approach on would need O(2^depth) memory where depth can be as large as n, where we only need O(n) memory in a linked implementation.
So my answer is: yes, this is the best way for a heap. Just don't try it for other binary trees (unless you're sure they will always be complete).