学点算法(十一)——将二叉树转为数组

今天我们来学习如何将二叉树转为数组(填坑学点算法(九)——二叉树中序遍历算法(递归实现))。

首先,我们看下面这棵二叉树,我们从根节点出发,左右孩子依次排列在根节点后面,放入数组中,然后继续以同样的方法遍历其左右孩子,如果孩子节点的位置已经被叔父节点占据,则继续排在叔父节点后面,如果遇到没有左右孩子的情况,则将没有的节点置为null,将节点排列在数组中,直至遍历结束,位于数组结尾的null(后面没有有效节点值)可去除。
在这里插入图片描述
我们来看下这个过程:

  1. 首先我们放入1及其左右孩子,得到[1, 2, 3]
  2. 1的左孩子2的左右孩子,因为2后面的位置被3占据了,所以4, 5需要排在3后面,得到[1, 2, 3, 4, 5]
  3. 1的右孩子3的左右孩子,因为3后面的位置被4, 5占据了,所以6, 7需要排在4, 5后面,得到[1, 2, 3, 4, 5, 6, 7]
  4. 4 5 6 7没有孩子节点,全部置为null,得到[1, 2, 3, 4, 5, 6, 7, null, null, null, null]因为null值都位于末尾,所以得到[1, 2, 3, 4, 5, 6, 7]

通过这个过程,可以发现节点的位置就是先到先得,谁先遇到了,就占据了这个位置,后面来的节点都往后排,这个过程跟队列的先进先出是一样的,所以我们很容易想到可以用队列来保存遇到的节点,并依次将它放到数组中。

/**
 * 将二叉树转为数组(二叉树层次遍历)
 * @param root 二叉树根节点
 * @param <T> 二叉树元素类型
 * @return 数组
 */
@SuppressWarnings("unchecked")
public static <T extends Comparable<T>> T[] convertTree2Array(BinaryTreeNode<T> root) {
    if (root == null) {
        // 如果根节点为null,则返回null
        return null;
    }
    // 由于不知道数组长度,先将元素存入list中
    List<T> list = new ArrayList<>();
    BinaryTreeNode<T> currentNode = root;
    Deque<BinaryTreeNode<T>> queue = new ArrayDeque<>();
    // 创建一个特殊对象来存储null
    BinaryTreeNode<T> NULL = new BinaryTreeNode<>(null);
    do {
        // 添加节点元素到列表中
        list.add(currentNode.data);
        if (currentNode != NULL) {
            // 获取左子树节点
            BinaryTreeNode<T> leftChild = currentNode.leftChild;
            if (leftChild == null) {
                queue.offer(NULL);
            } else {
                queue.offer(leftChild);
            }
            // 获取右子树节点
            BinaryTreeNode<T> rightChild = currentNode.rightChild;
            if (rightChild == null) {
                queue.offer(NULL);
            } else {
                queue.offer(rightChild);
            }
        }
        // 从队列中取出下一个节点
        currentNode = queue.poll();
    // 如果currentNode为null,表示没有剩余元素了,可退出循环
    } while (currentNode != null);
    return list.toArray((T[]) Array.newInstance(root.data.getClass(), 0));
}

代码中要注意的是NULL这个特殊对象,这个对象表示此处没有节点,但是在数组中我们还是需要放置一个null来表示,所以单独使用了一个特殊对象来存这个值。

测试代码如下:

BinaryTreeNode<Integer> one = new BinaryTreeNode<>(1);
BinaryTreeNode<Integer> two = new BinaryTreeNode<>(one, 2);
BinaryTreeNode<Integer> three = new BinaryTreeNode<>(one, 3);
one.leftChild = two;
one.rightChild = three;
BinaryTreeNode<Integer> four = new BinaryTreeNode<>(two, 4);
BinaryTreeNode<Integer> five = new BinaryTreeNode<>(two, 5);
two.leftChild = four;
two.rightChild = five;
BinaryTreeNode<Integer> six = new BinaryTreeNode<>(three, 6);
BinaryTreeNode<Integer> seven = new BinaryTreeNode<>(three, 7);
three.leftChild = six;
three.rightChild = seven;
Integer[] arr = convertTree2Array(one);
// 因为数组后面的null不影响数据,为了方便测试,将数组后面的null值都去掉
int idx = arr.length - 1;
while (arr[idx] == null) {idx--;}
Integer[] nullFilteredArr = Arrays.copyOf(arr, idx + 1);
assertArrayEquals(new Integer[]{1, 2, 3, 4, 5, 6, 7}, nullFilteredArr);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值