数据结构之完全二叉树

一、完全二叉树定义

完全二叉树(Complete Binary Tree)

若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。

一棵二叉树至多只有最下面的一层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
在这里插入图片描述

二、完全二叉树特点

1、叶子结点只可能在最大的两层上出现,对任意结点,若其右分支下的子孙最大层次为L,则其左分支下的子孙的最大层次必为L 或 L+1;
2、出于简便起见,完全二叉树通常采用数组而不是链表存储。
3、满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。
4、完全二叉树第i层至多有2(i-1)个节点,共i层的完全二叉树最多有2i-1个节点。
5、只允许最后一层有空缺结点且空缺在右边,即叶子结点只能在层次最大的两层上出现;
6、对任一结点,如果其右子树的深度为j,则其左子树的深度必为j或j+1。 即度为1的点只有1个或0个。

三、判断完全二叉树及实现方法

完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210317153436440.png在这里插入图片描述
实现方法
1、针对这个完全二叉树进行层序遍历;
2、判定是不是完全二叉树的时候,需要分成两个阶段来判定:
a)第一阶段,要求每个被访问到的节点,都要有两个子树
如果当前这个节点只有左子树,就需要进入第二阶段了;
如果当前节点没有子树,也是进入第二阶段;
如果当前节点只有右子树,那么直接认为这就不是完全二叉树。
b)第二阶段,要求每个被访问到的节点,必须没有子树。

四、层序遍历

上面描述中出现了层序遍历,现在我们来说一说层序遍历以及它的实现。

1、层序遍历的定义

层序遍历,就是按二叉树从上到下,从左到右依次打印每个节点中存储的数据。如下图:
在这里插入图片描述
层序遍历:ABCDEFG

2、层序遍历的实现方法

实现层序遍历,需要借助一个“队列”:
1、先把根节点放到队列里;
2、进行出队列操作,并且访问这个节点3,把当前节点的左子树和右子树再入队列(空树就不管了);
4.回到2继续循环执行.

3、代码实现
public static void levelOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (true) {
            TreeNode cur = queue.poll();
            if (cur == null) {
                break;
            }
            // 访问当前节点. 就用打印表示访问即可.
            System.out.print(cur.val);
            // 把该节点的左子树入队列, 右子树入队列
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
        }
    }

五、判断完全二叉树的代码实现

public static boolean isCompleteTree(TreeNode root) {
        // 通过层序遍历的方式来实现
        if (root == null) {
            return true;
        }
        // 分成两个阶段来进行判定
        // 这个变量为 false, 表示当前是第一阶段,
        // 变量为 true 表示进入第二阶段
        boolean isLevel2 = false;

        // 层序遍历, 需要有一个队列
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (true) {
            TreeNode cur = queue.poll();
            if (cur == null) {
                break;
            }
            // 针对当前节点进行访问.
            // 此处的访问是一系列的逻辑判断
            if (!isLevel2) {
                // 第一阶段的逻辑
                if (cur.left != null && cur.right != null) {
;                   // 这是一个符合要求的节点, 继续往下遍历即可.
                    // 此时直接把左右子树入队列即可
                    queue.offer(cur.left);
                    queue.offer(cur.right);
                } else if (cur.left == null && cur.right != null) {
                    // 第一阶段中发现只有右子树的节点!!
                    // 说明这个树一定不是完全二叉树
                    return false;
                } else if (cur.left != null && cur.right == null) {
                    // 遇到了这个节点不符合第一阶段的条件,
                    // 进入到第二阶段继续判定
                    isLevel2 = true;
                    queue.offer(cur.left);
                } else {
                    // 这个节点没有子树
                    // 也是进入到第二阶段继续判定
                    isLevel2 = true;
                }
            } else {
                // 第二阶段的逻辑
                if (cur.left != null || cur.right != null) {
                    // 发现第二阶段的某个节点的子树不为空, 此时就认为当前不是完全二叉树
                    return false;
                }
            }
        }
        // 遍历了整个树, 也没找到 return false 的反例.
        return true;
    }
  • 153
    点赞
  • 686
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
完全二叉树是一种特殊的二叉树,它的所有叶子节点都在同一层上,除了最后一层,其他层的节点数都是满的。在完全二叉树中,新节点应该从最后一层的最左边开始添加,如果最后一层已经满了,则新节点应该添加到下一层的最左边。下面是Python实现完全二叉树添加节点的示例代码: ```python class Node: def __init__(self, val): self.val = val self.left = None self.right = None class CompleteBinaryTree: def __init__(self): self.root = None def add_node(self, val): new_node = Node(val) if not self.root: self.root = new_node return queue = [self.root] while queue: cur_node = queue.pop(0) if not cur_node.left: cur_node.left = new_node return elif not cur_node.right: cur_node.right = new_node return else: queue.append(cur_node.left) queue.append(cur_node.right) ``` 在这个示例代码中,我们定义了一个Node类来表示二叉树的节点,以及一个CompleteBinaryTree类来表示完全二叉树。在add_node方法中,我们首先创建一个新节点,然后判断根节点是否为空,如果为空,则将新节点设置为根节点。如果根节点不为空,则将根节点添加到队列中,然后进行循环。在循环中,我们从队列中弹出当前节点,然后检查它的左右子节点是否为空。如果左子节点为空,则将新节点添加为左子节点,否则,如果右子节点为空,则将新节点添加为右子节点。如果左右子节点都不为空,则将左右子节点添加到队列中,以便在下一次循环中处理它们。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值