Java:如何逐级打印存储为数组的堆

Java:如何逐级打印存储为数组的堆,java,heap,Java,Heap,我有一个表示最大堆的数组。比如说 84 81 41 79 17 38 33 15 61 6 所以根是最大的。索引处的每个中间层节点最多可以有两个子节点。它们分别是2*i+1和2*i+2 如何以逐级方式打印此堆?像 84(0) 81(1) 41(2) 79(3) 17(4) 38(5) 33(6)

我有一个表示最大堆的数组。比如说

84 81 41 79 17 38 33 15 61 6
所以根是最大的。索引处的每个中间层节点最多可以有两个子节点。它们分别是2*i+1和2*i+2

如何以逐级方式打印此堆?像

                             84(0)

                 81(1)                  41(2)

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

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

数组中每个元素的索引如图1所示,以便于说明。我不必打印索引。我原以为这类似于按级别顺序打印BST,但在这里,堆存储在数组中,而不是列表中,这让它有点棘手

如果要将其存储在列表列表中(级别顺序),只需按2的每一次幂拆分一次,如1,2,4,8,16

    private ArrayList<ArrayList<Integer>> heapParse(int[] arr) {

    ArrayList<ArrayList<Integer>> heap = new ArrayList<ArrayList<Integer>>();
    int j=-1;
    for (int i=0; i< arr.length;i++){
        if(isPowerOfTwo(i+1)){                
            heap.add(new ArrayList<>());
            j++;
        }
        heap.get(j).add(arr[i]);
    }       
    return heap;
    }

    private boolean isPowerOfTwo(int i){
       return (i&(i-1))==0;
    }
private ArrayList heapParse(int[]arr){
ArrayList堆=新的ArrayList();
int j=-1;
对于(int i=0;i
尝试以下代码:

public class NewClass56 {
public static void main(String args[]){

    int a[] = new int[] {84 ,81 ,41 ,79 ,17 ,38 ,33 ,15 ,61 ,6};

    for(int i=0;i<10;i++){
        for(int j=0;j<Math.pow(2,i)&&j+Math.pow(2,i)<10;j++){
            System.out.print(a[j+(int)Math.pow(2,i)-1]+" ");

        }
        System.out.println();
    }



    }
}
public class NewClass56 {
public static void main(String args[]){

    int a[] = new int[] {84 ,81 ,41 ,79 ,17 ,38 ,33 ,15 ,61 ,6};
    StringBuilder sb = new StringBuilder();
    int max=0;
    for(int i=0;i<10;i++){
        for(int j=0;j<Math.pow(2,i)&&j+Math.pow(2,i)<10;j++){

            if(j>max){
                max=j;
            }
        }

    }

    for(int i=0;i<10;i++){
        for(int j=0;j<Math.pow(2,i)&&j+Math.pow(2,i)<10;j++){

            for(int k=0;(k<max/((int)Math.pow(2, i)));k++){
                sb.append(" ");
            }
            sb.append(a[j+(int)Math.pow(2,i)-1]+" ");

        }
        sb.append("\n");

    }



    System.out.println(sb.toString());

}
}

分而治之。创建子树的行列表,连接行,并为子树的根节点预先添加
字符串。还要确保线的长度相同,并且所有线都居中:

static String pad(String s, int lengthRigth, int length) {
    StringBuilder sb = new StringBuilder();

    for (int i = length - lengthRigth - s.length(); i > 0; i--) {
        sb.append(' ');
    }

    sb.append(s);

    for (int i = 0; i < lengthRigth; i++) {
        sb.append(' ');
    }

    return sb.toString();
}

static StringBuilder withSpacesAppended(String s, int spaceCount) {
    StringBuilder sb = new StringBuilder(s.length()+spaceCount).append(s);
    for (int i = 0; i < spaceCount; i++) {
        sb.append(' ');
    }
    return sb;
}

static void joinLists(List<String> list1, List<String> list2) {
    int i;
    final int size = list2.size();
    for (i = 0; i < size; i++) {
        list1.set(i, withSpacesAppended(list1.get(i), 2).append(list2.get(i)).toString());
    }
}

static List<String> createTreeStrings(int index, int[] array) {
    int child1 = 2 * index + 1;
    int child2 = 2 * index + 2;
    if (child1 >= array.length) {
        return new ArrayList<>(Collections.singletonList(toText(index, array)));
    } else {
        List<String> childList1 = createTreeStrings(child1, array);
        if (child2 < array.length) {
            joinLists(childList1, createTreeStrings(child2, array));
        }
        String text = toText(index, array);
        int currentLength = childList1.get(0).length();

        if (currentLength >= text.length()) {
            text = pad(text, (currentLength - text.length()) / 2, currentLength);
        } else {
            for (int i = 0, size = childList1.size(); i < size; i++) {
                childList1.set(i, pad(childList1.get(i), (currentLength - text.length()) / 2, currentLength));
            }
        }

        childList1.add(0, text);
        return childList1;
    }
}

static String toText(int index, int[] array) {
    return Integer.toString(array[index]) + '(' + index + ')';
}

还有另一种打印堆的方法。假设您拥有具有以下索引的结构(索引
0
是守护者,等于
Integer.MIN\u值,此处未显示):

它由数字数组表示。你在这里看到了什么?对,
1,3,7,15
。如果将它增加1,它将是
2、4、8、16

这些数字是多少?只是
2^级
。其中
级别
是从1到4的级别

我们如何计算这个水平?它是以2为底的指数的对数

以下是实现此方法的代码(请参见
dump
函数):

package org.solutions;
导入java.util.ArrayList;
导入java.util.array;
类堆{
公共ArrayList arr;
公共堆(){
this.arr=新的ArrayList();
arr.add(Integer.MIN_值);//添加监护人
}
公共无效添加(int x){
int i=阵列大小();
arr.add(x);
while(arr.get(i)
接受的答案创建了许多新行,并在显示时忽略最后一个元素。因此共享优化代码

public void display() {
        // n is number of elements in the heap
        // It can be further optimised by calculating height of the heap
        // and looping i only till height of the tree
        for (int i = 0; i <= n / 2; i++) {
            for (int j = 0; j < Math.pow(2, i) && j + Math.pow(2, i) <= n; j++) { // Each row has 2^n nodes
                System.out.print(heap[j + (int) Math.pow(2, i) - 1] + " ");
            }
            System.out.println();
        }
    }
public void display(){
//n是堆中的元素数
//它可以通过计算堆的高度来进一步优化
//我只会绕到树的高度

对于(int i=0;i现有的解决方案对我来说不起作用,所以这里有一种稍微不同的方法,我认为这种方法更容易让人阅读。此外,它不使用任何外部库。请注意,这假设数组的第一个点为空,因为通常基于数组的堆会跳过数组[0]。这将根据输入大小自动确定级别数,输入大小应为堆中的节点数。它将在每个空的点中添加
--
(例如,如果有13个节点的堆,则最后两个节点将显示为空)

private void打印堆(int[]堆,大小){
int maxDepth=(int)(Math.log(size)/Math.log(2));//以2为底的n个日志
StringBuilder hs=新建StringBuilder();//堆字符串生成器
对于(intd=maxDepth;d>=0;d--){//层数,我们向后构建此函数
int layerLength=(int)Math.pow(2,d);//每层的数字
StringBuilder line=新建StringBuilder();//行字符串生成器
对于(int i=layerllength;i<(int)Math.pow(2,d+1);i++){
//仅在最后一层上的空间之前
如果(d!=最大深度){
行.append(“.”repeat((int)Math.pow(2,maxDepth-d));
}
//长线的额外空间
int循环=最大深度-d;
如果(循环>=2){
循环-=2;
while(循环>=0){
行.append(“.”repeat((int)Math.pow(2,循环));
循环--;
}
}
//把数字加进去
如果(i=2){
循环-=2;
while(循环>=0){
行.append(“.”repeat((int)Math.pow(2,循环));
循环--;
}
}
}
hs.insert(0,line.toString()+“\n”);//预结束行
}
System.out.println(hs.toString());
}
输入示例:

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

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

如果需要的话,您应该能够相当容易地将其更改为toString方法
public void display() {
        // n is number of elements in the heap
        // It can be further optimised by calculating height of the heap
        // and looping i only till height of the tree
        for (int i = 0; i <= n / 2; i++) {
            for (int j = 0; j < Math.pow(2, i) && j + Math.pow(2, i) <= n; j++) { // Each row has 2^n nodes
                System.out.print(heap[j + (int) Math.pow(2, i) - 1] + " ");
            }
            System.out.println();
        }
    }
int[] heap = new int[]{0, 84, 81, 41, 79, 17, 38, 33, 15, 61, 6};
int size = heap.length-1 = 10
           84           
     81          41     
  79    17    38    33  
15 61 6  -- -- -- -- --