算法与数据结构——树

树的基本概念

树的定义

树是n(n>=0)个结点的有限集。当n=0时,称为空树。在任意一颗非空树中应满足:

  1. 有且仅有一个特定的称为根的结点。
  2. 当n>1时,其余节点可分为m个互不相交的有限集合,其中每个集合本身又是一棵树,并且称为根结点的子树。

由上可以看出,树是一种递归定义的数据结构。

同时,树也是一种分层结构,具有以下的两个特点:

  1. 树的根节点没有前驱,除根节点外的所有节点有且仅有一个前驱。
  2. 树中所有结点可以由零个或多个后继。

基本术语

树中一个结点的孩子个数称为结点的度

树中最大的度数称为树的度

深度、高度和层次

结点的层次从树根开始定义,根结点为第1层,它的子结点为第二层。以此类推。

结点的深度是从根结点开始自顶向下逐层累加的。(默认是从1开始的)

结点的高度是从叶结点开始逐层累加的。

树的高度(深度)是树中结点的最大层数。即,总共有多少层。

路径和路径长度

树中两个结点之间的路径是由这两个结点之间所经过的结点序列构成的。路径只能是从上往下的。

路径长度是路径上所经过的边的个数。

有序树和无序树

无序树——从逻辑上看,树中结点的各子树从左至右是有次序的,不能互换。

无序树——从逻辑上看,树中结点的各子树从左至右是无次序的,可以互换。

森林

m棵互不相交的树的集合。

比如,可以用森林来表示全中国所有家庭的家谱。

树的性质

  1. 结点数 = 总度数 + 1
  2. 度为m的数与m叉树

度为m的树要求必须有一个结点,这个结点有三个子结点。

m叉树,它规定一个结点最多有m个孩子。但是,存在每一个结点都不足m个孩子的情况。

  1. 度为m的树第i层最多有m^(i-1)个结点。

  2. 高度为h的m叉树至多有
    $$
    \frac{m^h-1}{m-1}
    $$
    个结点。

  3. 高度为h的m叉树至少有h个结点;高度为h、度为m的树至少有 h + m - 1个结点。

  4. 具有n个结点的m叉树最小高度为
    $$
    \log_m{(n(m-1) + 1)}
    $$
    计算结果向上取整。

二叉树

二叉树的定义及其主要特征

二叉树的定义

​ 二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能颠倒。

​ 与树相似,二叉树也以递归的形式定义。二叉树是n个结点的优先集合:

  1. 或者为空二叉树,即n=0

  2. 或者由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一棵二叉树。

    二叉树是一个有序树,如将其左、右子树颠倒,则成为另一棵不同的二叉树。

几个特殊的二叉树

满二叉树

一棵高度为h,且含有 2^h - 1 个结点的二叉树

特点

  1. 只有最后一层有叶子结点
  2. 不存在度为1的结点
  3. 按层序从1开始编号,结点 i 的右孩子为 2i,右孩子为 2i+1;结点i的父节点为 i / 2 (向下取整)
完全二叉树

当且仅当其每个结点都与高度为h的满二叉树中编号为 1 ~ h的结点一一对应时,称之为完全二叉树。

特点

  1. 只有最后两层可能有叶子结点
  2. 最多只有一个度为1的结点
  3. 同满二叉树的 3
  4. i <= n /2 ( 向下取整 ) 为分支节点, i > n /2 (向下取整)为叶子结点。
二叉排序树

左子树上所有结点的关键字均小于根结点的关键字

右子树上所有结点的关键字均大于根结点的关键字

左子树和右子树又各是一棵二叉排序树

平衡二叉树

树上任一结点的左子树右子树深度之差不超过1

二叉树的性质

非空二叉树上的叶子结点数量等于度为2的结点数加1,即:
$$
n_0 = n_2 + 1
$$
二叉树第i层存在的结点个数为
$$
2^{i-1}
$$
高度为h的二叉树至多有的结点个数为
$$
2^h - 1
$$
完全二叉树的高度h可以通过以下两个公式进行计算
$$
log_2{n+1} (向上取整)

log_2{n} + 1 (向下取整)
$$

二叉树的存储结构

顺序存储结构

#define MAXSIZE 100
struct TreeNode {
    ElemType value;
    bool isEmpty;
}
TreeNode t[MAXSIZE];

定义一个长度为MAXSIZE的数组t,按照从上至下、从左至右的顺序依次存储完全二叉树的各个结点。

最坏情况:高度为h且只有h个结点的单支树(所有结点只有右孩子),也至少需要2^h - 1个存储单元。

二叉树的顺序存储结构,只适合存储完全二叉树

链式存储结构

typedef struct BiTNode {
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree

n个结点的二叉链表共有n +1 个空链域。

问题:找到一个结点p的父节点,只能从头开始遍历。如果当链表体量十分大的时候,这种操作是十分耗时的。

这个时候,可以使用三叉链表,方便找到父结点

posted @ 2022-06-16 21:13  Gazikel  阅读(168)  评论(0编辑  收藏  举报