Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java : How to print heap stored as array, level by level

Tags:

java

heap

I have an array that represents a Max Heap. For example

84 81 41 79 17 38 33 15 61 6

so the root is max. Each mid tier node at index i can have at most two children. They would be at 2*i+1 and 2*i+2.

How can i print this heap out in a level by level fashion? like

                             84(0)

                 81(1)                  41(2)

            79(3)        17(4)     38(5)       33(6) 

       15(7)    61(8)         6(9)

the index of each element in the array is shown in paranthesis for clarification. i dont have to print the index. I was thinking it would be similar to printing a BST in level order but here, the heap is stored in an array not a list which makes it a bit tricky!

like image 975
AbtPst Avatar asked Apr 03 '16 13:04

AbtPst


1 Answers

The existing solutions didn't work for me so here's slightly different way of doing it that I think is also more human readable. Additionally, this doesn't use any external libraries. Note that this assumes that the first spot of the array is null, because often array-based heaps skip the array[0]. This will automatically determine the number of levels based on the input size which should be the number of nodes in the heap. It will add -- in every spot that is empty (e.g. if you have a 13-node heap the last two nodes will show up as empty).

private void printHeap(int[] heap, size) {
    int maxDepth = (int) (Math.log(size) / Math.log(2));  // log base 2 of n

    StringBuilder hs = new StringBuilder();  // heap string builder
    for(int d = maxDepth; d >= 0; d--) {  // number of layers, we build this backwards
        int layerLength = (int) Math.pow(2, d);  // numbers per layer

        StringBuilder line = new StringBuilder();  // line string builder
        for(int i = layerLength; i < (int) Math.pow(2, d + 1); i++) {
            // before spaces only on not-last layer
            if(d != maxDepth) {
                line.append(" ".repeat((int) Math.pow(2, maxDepth - d)));
            }
            // extra spaces for long lines
            int loops = maxDepth - d;
            if(loops >= 2) {
                loops -= 2;
                while(loops >= 0) {
                    line.append(" ".repeat((int) Math.pow(2, loops)));
                    loops--;
                }
            }

            // add in the number
            if(i <= size) {
                line.append(String.format("%-2s", heap[i]));  // add leading zeros
            } else {
                line.append("--");
            }

            line.append(" ".repeat((int) Math.pow(2, maxDepth - d)));  // after spaces
            // extra spaces for long lines
            loops = maxDepth - d;
            if(loops >= 2) {
                loops -= 2;
                while(loops >= 0) {
                    line.append(" ".repeat((int) Math.pow(2, loops)));
                    loops--;
                }
            }
        }
        hs.insert(0, line.toString() + "\n");  // prepend line
    }
    System.out.println(hs.toString());
}

Example input:

int[] heap = new int[]{0, 84, 81, 41, 79, 17, 38, 33, 15, 61, 6};
int size = heap.length-1 = 10

Example output:

           84           
     81          41     
  79    17    38    33  
15 61 6  -- -- -- -- -- 

You should be able to fairly easily change this to work as a toString method instead if necessary. The spacing will have to be modified if you want to use 3-digit numbers, if someone requests it I can edit with modified code for that.

like image 97
elkshadow5 Avatar answered Oct 15 '22 21:10

elkshadow5