复旦大学961-数据结构-第二章-树(4)-完全树的数组存储形式

961全部内容链接

完全二叉树的数组表示形式

完全二叉树的Java定义

public class CompleteBinaryTree {

    private final static int MAX_SIZE = 100;
    Object[] elements = new Object[MAX_SIZE];
    int size; // 当前完全二叉树的元素个数
}

完全二叉树的前序遍历(递归)

private static void preOrder(Object[] elements, int i) {
    if (i>=elements.length || elements[i] == null) return;
    System.out.print(elements[i] + " " );  // 输出根节点
    preOrder(elements, i * 2); // 访问左孩子
    preOrder(elements, i * 2 + 1); // 访问右孩子
}

public static void preOrder(CompleteBinaryTree tree) {
    preOrder(tree.elements, 1); // 从1开始,0不存储数据,方便计算
}

完全二叉树的前序遍历(非递归)

public static void preOrder(CompleteBinaryTree tree) {
    Object[] elements = tree.elements;
    int i = 1; // 第0个位置不存储数据,方便计算
    Set set = new HashSet(); // 用于记录已经被访问过的节点
    while (i > 0) {
        if (!set.contains(elements[i])) {
            // 若该节点没有被访问过,则访问该节点,并记录
            System.out.print(elements[i] + " ");
            set.add(elements[i]);
        }
        if (i * 2 < elements.length && elements[i * 2] != null  // 若有左孩子且没有被访问过,则访问左孩子
                && !set.contains(elements[i * 2])) {
            i = i * 2; // 访问左孩子
        } else if (i * 2 + 1 < elements.length && elements[i * 2 + 1] != null &&
                !set.contains(elements[i * 2 + 1])) { // 若有右孩子且没有被访问过,则访问右孩子
            i = i * 2 + 1; // 访问右孩子
        } else {
            i = i / 2; // 如果左右孩子都为空,或都被访问过,则回到父节点;
        }
    }
}

基本思路:

  1. 初始化一个Set集合,来存放已经被访问过的节点
  2. 从根节点开始,若根节点没访问过,则访问,然后判断其左子树是否被访问过,若没访问过,则访问左子树,若左子树被访问过,则判断右子树是否被访问过,若右子树没有被访问则访问右子树。若左右子树都被访问过,则返回当前节点的父节点。

这里我使用了一个Set来记录被访问过的左右节点,所以空间复杂度为O(n)。实际上根本没必要。但是没仔细想怎么弄,欢迎在评论区帮忙改正。

方法二:与普通二叉树的非递归前序遍历一样的方式

public static void preOrder(CompleteBinaryTree tree) {
    Object[] elements = tree.elements;
    int i = 1; // 第0个位置不存储数据,方便计算
    Stack<Integer> stack = new Stack<>(); // 初始化栈,用于存储各个子树的根节点
    while (i < tree.size + 1 || stack.size() > 0) { // 如果要访问的节点不为空或者栈不为空,则继续
        if (i < tree.size + 1) { // 如果要访问的节点不为空,则输出,然后入栈,接着访问其左子树
            System.out.print(elements[i] + " ");
            stack.push(i);
            i = i * 2;
        } else { // 若要访问的节点为空,则从栈中弹出一个根节点,然后访问该根节点的右子树
            int temp = stack.pop();
            i = temp * 2 + 1;
        }
    }
}

完全二叉树的中序遍历(递归)

private static void inOrder(Object[] elements, int i) {
    if (i>=elements.length || elements[i] == null) return;
    inOrder(elements, i * 2); // 访问左孩子
    System.out.print(elements[i] + " " );  // 输出根节点
    inOrder(elements, i * 2 + 1); // 访问右孩子
}

public static void inOrder(CompleteBinaryTree tree) {
    inOrder(tree.elements, 1); // 从1开始,0不存储数据,方便计算
}

完全二叉树的中序遍历(非递归)

todo

完全二叉树的后序遍历(递归)

private static void postOrder(Object[] elements, int i) {
    if (i>=elements.length || elements[i] == null) return;
    postOrder(elements, i * 2); // 访问左孩子
    postOrder(elements, i * 2 + 1); // 访问右孩子
    System.out.print(elements[i] + " " );  // 输出根节点
}

public static void postOrder(CompleteBinaryTree tree) {
    postOrder(tree.elements, 1); // 从1开始,0不存储数据,方便计算
}

完全二叉树的后序遍历(非递归)

todo

完全n叉树的数组存储形式

todo 应该不考,先不弄

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iioSnail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值