Search code examples
javadata-structuresbinary-heap

why are binary heaps a tree structure?


Binary Heaps can be represented using array which is a linear data structure, contrast to a tree, which is a non-linear data structure. Does that mean that binary heap represented using an array is no longer a tree?


Solution

  • You're confusing the model--the conceptual view of the heap--with the implementation.

    A binary heap is a tree that is implemented in an array. That is, we allocate a fixed block of memory and reference it as though it's a tree. We can do that because the binary heap is a very special type of tree. In concept this is not much different than how we implement a two-dimensional array.

    Consider a two-dimensional array declared as a[3,4]. Most languages allocate that as a single block of memory--a linear array--of size 12. But we address it as though it's a two-dimensional structure. The compiler converts our 2D addressing to one-dimensional array indices (assuming row-major ordering), like this:

     1 2 3 4 5 6 7 8 9 10 11 12
    | Row 1 | Row 2 |  Row 3
    

    In our two-dimensional view it looks like this:

     1  2  3  4
     5  6  7  8
     9 10 11 12
    

    So a[2,3] resolves to index 7.

    What does that have to to with heaps?

    Because a binary heap is a complete binary tree in which all levels except possibly the last are full, and the last is left-filled (i.e. all empty space is on the right side of the last level), we can overlay a tree structure on the array in much the same way we overlay the two-dimensional array.

    We know that the first element of the array is the root of the heap. We know that the next two array elements are children of the root. The next four elements are those children's children, and so on. So in a binary heap with 15 nodes we have:

    • Index 1 - root node
    • Indices 2 and 3 - Children of root node
    • Indices 4,5,6,7 - Children of root's children (4 and 5 are children of the node at index 2. 6 and 7 are children of the node at index 3).
    • Indices 8 through 15 - Children of nodes at indices 4-7.

    That leads to a view of the array that looks like this:

    1
    2 3
    4 5 6 7
    8 9 10 11 12 13 14 15
    

    Or, viewed as a tree:

                1
          2           3
       4     5     6     7
      8 9  10 11 12 13 14 15
    

    The binary heap is still a tree. We're just using our knowledge of the special nature of a binary heap to implement it more efficiently than we can implement other types of trees.

    Yes, we are using a linear data structure to implement a non-linear data structure. But that's true of all the data structures we use. Early processors (think 8086 and before) viewed memory as essentially one big array. Software would essentially split that up into different areas for operating system, program code, processor stack, process heap, etc. And within the process heap (again, one big linear data structure), programs would allocate and deallocate individual blocks to build non-linear data structures. Even today's systems, with memory virtualization and address translation, things work much the same way: your program allocates large blocks of linear memory and manages them, parceling out small pieces for non-linear data structures.

    And then there's the linked list: a linear data structure that's implemented in terms of a non-linear data structure. Again, the model is a list--a linear data structure. The implementation is not linear at all.

    And then consider implementing a linked list in an array. Each element of the array contains the node data and an index to the next item in the list. Traversed in order, the list nodes might be at array indices 1,7,5,4,6,2,3. Whether that's a linear or non-linear data structure depends on how you're looking at the problem. Or perhaps which part of the implementation you're looking at. Again, the model of the list is linear. And the implementation is in a linear data structure (the array). But the first node in the list is at the beginning of the array, the second node is at the end, and the nodes in the middle are in essentially random order. It's not linear at all!

    You must learn to separate the model from the implementation.