23.二叉树基础(一)

文章目录

    • 基本概念
    • 高度
    • 深度
  • 二叉树(Binary Tree)
    • 满二叉树
    • 完全二叉树
    • 存储二叉树
      • 链式存储: 基于链表
      • 顺序存储:基于数组
      • 比较
    • 二叉树的遍历
      • 前序遍历
        • 概念
        • 代码
      • 中序遍历
        • 概念
        • 代码
      • 后序遍历
        • 概念
        • 代码

如下图:

23.二叉树基础(一)_第1张图片

基本概念

​ A 为 B 父节点, B为A的子节点

​ B,C,D父节点为同一个,他们成为兄弟节点

​ 根节点:没有父节点的节点,比如E

​ 叶子节点(叶节点):没有子节点的节点,比如GHIJ

23.二叉树基础(一)_第2张图片

高度

23.二叉树基础(一)_第3张图片

高度,从下往上看,比如第一层楼高,第二层楼高。计数从0开始。

深度

深度,从上往下看,比如水的深度。计数从0开始。

层,与深度类似,只不过从1开始。

二叉树(Binary Tree)

​ 每个节点,最多有两个”叉“,也就是两个子节点,分别是左子节点和右子节点。并不要求都有两个子节点,可以只有一个左子节点或者只有一个右子节点。

23.二叉树基础(一)_第4张图片

满二叉树

​ 上图编号2中,除叶子节点外,每个节点都有左右两个子节点,这种树叫满二叉树

完全二叉树

​ 上图编号3中,有以下三个特点:

  • 叶子节点都在最底下两层

  • 最后一层的叶子节点都靠左排列(如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树)

  • 除了最后一层,其他层的节点个数都要达到最大

    23.二叉树基础(一)_第5张图片

存储二叉树

链式存储: 基于链表

23.二叉树基础(一)_第6张图片

顺序存储:基于数组

​ 根节点放于下标i=1的位置,那么左子节点位置为2*i, 右子节点位置为2*i+1,

反过来,节点为i, 则,父节点的位置为 i/2, 完全二叉树,为便于理解,一般从下标为1开始,浪费了

一个而空间。

23.二叉树基础(一)_第7张图片

而,非完全二叉树,浪费的空则较多:

23.二叉树基础(一)_第8张图片

比较

  • 链式储存法,需要保存左右两个子节点的指针位置,多一些空间
  • 顺序存储,如果不是完全二叉树,会浪费角度的空间
  • 数组与链表的区别:
    • 数组对cpu友好
    • 数组随机访问快,空间占用少,但是需要连续内存

二叉树的遍历

为什么分三种遍历?个人思考是,有些数据存储是有序的,比如平衡二叉树,通过中序遍历,就能得到从小到大的有序数据。

23.二叉树基础(一)_第9张图片

前序遍历

概念

​ 根节点 -> 左子节点 -> 右子节点

代码

​ 采用递归: 递归三条件:

  • 问题可分解为子问题

  • 子问题的求解方法与父问题一致,只是数据规模不同而已

  • 存在终止条件

    写出递归代码步骤:

    • 大问题化为小问题,屏蔽嵌套逻辑,从某一层开始
    • 写出递推公式
    • 找到终止条件
    • 翻译成代码
    /**
         *      a
         *   b     c
         * d  e  f  g
         * 前序遍历: m -> l -> r.
         * 递推公式:print(r) -> printOrder(r.left) -> printOrder(r.right)
         * 终止条件:节点为叶子节点(getLeft == null && getRight == null). 只打印自己.
         *  a->b->d->e->c->f->g
         *
         *  复杂度:一个节点,最多两次(第一次遍历算一次;递归回来,算一次)
         *    最好:O(n)
         *    最坏:O(n)
         *    平均:O(n)
         * @param root
         */
        public static void before(Node root) {
            if(root == null) {
                return;
            }
            System.out.print(root);
            before(root.getLeft());
            before(root.getRight());
    
            // or
    
    //        if(root != null) {
    //            System.out.print(root);
    //        }
    //
    //        if(root.getLeft() == null && root.getRight() == null) {
    //            return;
    //        }
    //
    //        before(root.getLeft());
    //        before(root.getRight());
        }
    
    
    @Data
        @NoArgsConstructor
        @AllArgsConstructor
        private static class Node {
            private String data;
            private Node left;
            private Node right;
    
            public Node(String data) {
                this.data = data;
            }
    
            @Override
            public String toString() {
                return data + "->";
            }
        }
    

中序遍历

概念

​ 左子节点 -> 根节点 -> 右子节点

代码

/**
     *      a
     *   b     c
     * d  e  f  g
     * 中序遍历: l -> m -> r.
     * 递推公式:printOrder(r.left) -> print(r)-> printOrder(r.right)
     * 终止条件:节点为叶子节点(getLeft == null && getRight == null). 只打印自己.
     *  d->b->e->a->f->c->g
     *
     *  复杂度:一个节点,最多两次(第一次遍历算一次;递归回来,算一次)
     *    最好:O(n)
     *    最坏:O(n)
     *    平均:O(n)
     * @param root
     */
    public static void middle(Node root) {
        if (root == null) {
            return;
        }

        middle(root.getLeft());
        System.out.print(root);
        middle(root.getRight());
    }

后序遍历

概念

​ 左子节点 -> 右子节点 -> 根节点

代码

/**
     *      a
     *   b     c
     * d  e  f  g
     * 后序遍历: l -> r -> m.
     * 递推公式:printOrder(r.left) -> printOrder(r.right) -> print(r)
     * 终止条件:节点为叶子节点(getLeft == null && getRight == null). 只打印自己.
     * d->e->b->f->g->c->a
     *
     * 复杂度:一个节点,最多两次(第一次遍历算一次;递归回来,算一次)
     *    最好:O(n)
     *    最坏:O(n)
     *    平均:O(n)
     * @param root
     */
    public static void after(Node root) {
        if (root == null) {
            return;
        }

        after(root.getLeft());
        after(root.getRight());
        System.out.print(root);
    }

你可能感兴趣的:(数据结构与算法)