美文网首页
二叉树(上)

二叉树(上)

作者: GallenZhang | 来源:发表于2019-03-14 01:33 被阅读0次

先通过几张图来看看,什么是树,这些"树"都有哪些特征。

"树"这种结构就像我们生活中见到的"树", “树”中的每个元素称之为"节点",用连线来表示节点间的"父子关系"。

比如上面的图1,A节点就是B节点的"父节点",B节点就是A节点的"子节点"。B、C的父节点是同一个节点,所以他们是"兄弟节点"。我们把没有父节点的节点叫做"根节点",图中的根节点就是节点A。把没有子节点的节点叫做"叶子节点",这里的是E、F、G都是叶子节点。

除了了解树的基本特征之外,还有三个概念需要了解一下:高度深度

  • 节点的高度=节点到叶子节点的最长路径
  • 节点的深度=根节点到这个节点经历的边的个数
  • 节点的层数=节点的深度 + 1
  • 树的高度 = 根节点的高度

文字描述起来挺不容易理解的,通过图示来说明,会更直观明了。

关于高度、深度、层的,其实可以类比生活中的含义。
"高度"是从下往上度量的,比如建筑物的高度,是从地面开始度量的。这里树的高度类似,从最底层的叶子节点开始计数,计数起点是0。

"深度"是从上往下度量的,比如水井的深度,是从上开始度量的。这里树的深度也是类似,从最上层的根节点开始计数,计数起点是0。

"层"就是节点的深度加1,计数起点是1,根节点位于第1层。

二叉树

"树"有多种多样的,不过最常用的还是二叉树。

二叉树,就是每个节点最多只有两个子节点,分别是左子节点右子节点。二叉树不要求每个节点都有左右子节点,有的节点只有左子节点,有的节点只有右子节点。

这里有两个比较特殊的二叉树,分别是图2的满二叉树,图3的完全二叉树。

满二叉树:叶子节点都在最底层,除了最底层的叶子节点之外,其他的每个节点都有左右子节点。
完全二叉树:叶子节点在最底下两层,除了最底层,其他层节点个数都是满的,最底层的节点都靠左排列。

二叉树的存储

二叉树有两种存储方式,一种是基于指针的链式存储法,还有一种是基于数组的顺序存储法。

首先看下最常用的“链式存储”,每个节点包含三个字段,分别是:数据、左节点指针、右节点指针。只要根据根节点,就可以通过每个节点的左右指针就能将整棵树进行遍历。

class Node{
    Node left;
    Node right;
    T data;
}

再来看一下“数组存储”,这种存储方式一般应用于完全二叉树。为了方便计算,元素存储从数组下标1的位置开始,我么把根节点放置在数组下标为1的位置。对于下标为i的节点, 其左子节点的下标就是 i2,右子节点的下标为 i2 + 1,其父节点的数组下标为i / 2。通过下标,可以将整棵树进行遍历。采用“数组存储”只会浪费一个下标为0的位置,如果是非完全二叉树,那么会浪费比较多的数组存储空间。

二叉树的遍历

二叉树遍历方法比较经典的有三种,前序遍历、中序遍历、后续遍历。这里的前、中、后序指的是节点与它的左右子树遍历打印的先后顺序。

前序遍历:对于树中的任意节点来说,先打印这个节点,再打印它的左子树,最后打印它的右子树。
中序遍历:对于树中的任意节点来说,先打印它的左子树,再打印这个节点,最后打印它的右子树。
后续遍历:对于树中的任意节点来说,先打印它的左子树,再打印它的右子树,最后打印这个节点。

二叉树的前、中、后序遍历一般都是用递归来实现的。递归代码的关键,是写出递推公式。要解决问题A,先假设子问题B、C已经解决,然后再看如何利用B、C来解决A,递归终止条件就是出口。

public void preOrder(Node root){
    if(root == null){
        return;
    }

    print(root.data);
    preOrder(root.left);
    preOrder(root.right);
}

public void inOrder(Node root){
    if(root == null){
        return;
    }

    preOrder(root.left);
    print(root.data);
    preOrder(root.right);
}

public void postOrder(Node root){
    if(root == null){
        return;
    }

    preOrder(root.left);
    preOrder(root.right);
    print(root.data);
}

二叉树的遍历除了上面三种经典的方式外,还有一种是层序遍历。所谓层序遍历,就是利用"队列"这种数据结构实现,从第1层开始一直到最后一层通过顺序遍历每一层的所有节点来完成树的遍历。二叉树的层序遍历,与图的广度优先遍历的思路是如出一辙。

二叉树遍历的时间复杂度

在递归遍历二叉树的过程中,每个节点最多被访问两次。所以遍历的时间复杂度与节点个数n成正比,也就是说二叉树遍历的时间复杂度为O(n)。

GitHub 代码地址: 二叉树

相关文章

  • 二叉树的基本算法

    二叉树的基本算法 树、二叉树 的基本概念,参考数据结构算法之美-23讲二叉树基础(上):树、二叉树[https:/...

  • HeapSort学习笔记

    完全二叉树 堆排序 什么是堆(Heap)? 堆本质上是一棵二叉树,而且是完全二叉树。 (注:从严格意义上讲,堆可以...

  • 二叉树—线索二叉树

    1、线索二叉树的引入 在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或...

  • 二叉树分析

    二叉树分类 满二叉树: 除最后一层无任何子外,每一层上的所有结点都有两个子结点二叉树。 完全二叉树:若设二叉树的深...

  • 数据结构与算法13-线索二叉树

    定义 在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历...

  • 线索化二叉树的实现

    概念   在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行...

  • 数据结构与算法[线索化二叉树]

    在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其...

  • golang队列二叉树的实现

    关于二叉树的代码实现,这里主要介绍的是完全二叉树的情形。引用百度百科上对完全二叉树的判定:若设二叉树的深度为h,除...

  • Avl平衡树--C语言实现

    Avl 平衡树 实现记录 Avl平衡二叉树和搜索二叉树基本实现原理相同,在搜索二叉树的基础上添加树平衡的操作--单...

  • 二叉树-链表存储,用二叉树构造表达式(Python实现)

    既然用到二叉树了,直观上链表的方式比较容易接受,下面用python实现简单的二叉树。二叉树是递归结构,Python...

网友评论

      本文标题:二叉树(上)

      本文链接:https://www.haomeiwen.com/subject/pqjapqtx.html