日撸java 三百行 (day 12 )二叉树的存储

这篇博客介绍了如何使用两个数组来存储完全满二叉树,利用层序遍历的方法,结合队列数据结构,实现节点值和位置的存储。通过示例代码展示了如何创建一个循环对象类型队列,并在遍历二叉树过程中填充这两个数组。这种方法避免了大量空值的存储,提高了空间效率。
摘要由CSDN通过智能技术生成

今天的代码联动性比较强,需要用到辅助队列(之前写的改一下就派上用场),目标是要存储一颗二叉树。根据老师的描述:

我们可以完全满二叉树的角度广度优先遍历的角度来考虑这个问题: 每个节点都有一个 name 及其在二叉树中的位置. 令根节点的位置为 0; 则第 2 层节点的位置依次为 1 至 2; 第 3 层节点的位置依次为 3 至 6. 以此类推.
把昨天那个例子所对应的二叉树画出来, 我们有两种方法:

空使用 0 来表示, 可以用一个向量来存储:
[a, b, c, 0, d, e, 0, 0, 0, f, g]
优点: 仅需要一个向量, 简单直接.
缺点: 对于实际的二叉树, 很多子树为空, 导致大量的 0 值.
应使用压缩存储方式, 即将节点的位置和值均存储. 可表示为两个向量:
[0, 1, 2, 4, 5, 9, 10]
[a, b, c, d, e, f, g]


首先创建一个object类型的队列一会要用,直接在之前的代码上改:

package com.day09;


/**
 * 循环对象类型队列.
 */
public class CircleObjectQueue {

    /**
     * The total space. One space can never be used.
     */

    public static final int TOTAL_SPACE = 10;

    /**
     * The data.
     */
    Object[] data;

    /**
     * The index of the head.
     */
    int head;

    /**
     * The index of the tail.
     */
    int tail;

    /**
     *******************
     * The constructor
     *******************
     */
    public CircleObjectQueue() {
        data = new Object[TOTAL_SPACE];
        head = 0;
        tail = 0;
    }// Of the first constructor

    /**
     *********************
     * Enqueue.
     *
     * @param paraValue
     *            The value of the new node.
     *********************
     */
    public void enqueue(Object paraValue) {
        if ((tail + 1) % TOTAL_SPACE == head) {
            System.out.println("Queue full.");
            return;
        } // Of if

        data[tail % TOTAL_SPACE] = paraValue;
        tail++;
    }// Of enqueue

    /**
     *********************
     * Dequeue.
     *
     * @return The value at the head.
     *********************
     */
    public Object dequeue() {
        if (head == tail) {
            //System.out.println("No element in the queue");
            return null;
        } // Of if

        Object resultValue = data[head % TOTAL_SPACE];

        head++;

        return resultValue;
    }// Of dequeue
}// Of CircleObjectQueue

之后接着昨天的代码加点两个属性与一个存储的方法:

    /**
     * 节点值数组
     */
    char[] valuesArray;

    /**
     * 与节点值对应的下标数组
     */
    int[] indicesArray;

    /**
     * *******************
     * 将二叉树表示成两个数组
     * 结果存储到两个成员变量中
     *
     * @see #valuesArray
     * @see #indicesArray
     * ********************
     */
    public void toDataArrays() {
        //数组长度由昨天写的方法得到.
        int tempLength = getNumNodes();

        valuesArray = new char[tempLength];
        indicesArray = new int[tempLength];
        int i = 0;

        //遍历的同时更新数组
        CircleObjectQueue tempQueue = new CircleObjectQueue();
        tempQueue.enqueue(this);
        //CircleIntQueue tempIntQueue = new CircleIntQueue();
        CircleObjectQueue tempIntQueue = new CircleObjectQueue();
        tempIntQueue.enqueue((Integer)0);

        BinaryCharTree  tempTree= (BinaryCharTree) tempQueue.dequeue();
        Integer tempIndex = (Integer) tempIntQueue.dequeue();

        while (tempTree != null) {
            valuesArray[i] = tempTree.value;
            indicesArray[i] = tempIndex;
            i++;

            if (tempTree.leftChild != null) {
                tempQueue.enqueue(tempTree.leftChild);
                tempIntQueue.enqueue((Integer)tempIndex * 2 + 1);
            } // Of if

            if (tempTree.rightChild != null) {
                tempQueue.enqueue(tempTree.rightChild);
                tempIntQueue.enqueue((Integer)tempIndex * 2 + 2);
            } // Of if

            tempTree = (BinaryCharTree) tempQueue.dequeue();
            tempIndex = (Integer) tempIntQueue.dequeue();
        } // Of while
    }// Of toDataArrays
    /**
     * ********************
     * The entrance of the program.
     *
     * @param args Not used now.
     *             ********************
     */
 public static void main(String args[]) {
        BinaryCharTree tempTree = manualConstructTree();
        tempTree.toDataArrays();
        System.out.println("The values are: " + Arrays.toString(tempTree.valuesArray));
        System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));
    }// Of main

运行结果:

总结:

  • 二叉树的存储这块感觉以前没怎么接触过,我个人理解二叉树的存储就是如何表示出二叉树,或者当我们要通过输入创建二叉树时,要输入什么,才能让计算机知道我们输入的是二叉树,而不是一堆无意义的数字。很容易想到暴力的使用领接表,但是空间利用率太低,所以根据老师的代码从完全满二叉树本身的性质入手,如果是我就很难想到用两个数组来表示出二叉树。
  • 今天还使用了object类型的队列,队列里面放二叉树的节点,当然也能放Integer类型的对象,所以我两个队列都是object类型。
  • 今天用到了层序遍历,层寻遍历的效果刚好与满二叉树的编号契合。相比于递归,层序遍历就要清晰明了多了,没有弯弯绕绕,以前:这还要借用队列真麻烦,现在:真好用,真方便,清晰明了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值