树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解

树的基本概念

树的定义

树是 n ( n ≥ 0 ) {\rm n(n \ge 0)} n(n0) 个结点的有限集。当 n = 0 {\rm n=0} n=0 时,称为空树。在任意一棵非空树中应满足:

  • 有且仅有一个特定的称为根的结点。
  • n > 1 {\rm n>1} n>1 时,其余结点可分为 m ( m > 0 ) {\rm m(m>0)} m(m>0) 个互不相交的有限集 T 1 , T 2 , ⋯   , T m {\rm T_1,T_2, \cdots ,T_m} T1,T2,,Tm ,其中每个集合本身又是一棵树,并且称为根的子树

显然,树的定义是递归的,即在树的定义中又用到了其自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:

(1)树的根结点没有前驱,除根结点外的所有结点有且只有一个前驱。

(2)树中所有结点可以有零个或多个后继

树适合于表示具有层次结构的数据。树中的某个结点(除根结点外)最多只和上一层的一个结点(即其父结点)有直接关系,根结点没有直接上层结点,因此在 n {\rm n} n 个结点的树中有 n − 1 {\rm n-1} n1 条边。 而树中每个结点与其下一层的零个或多个结点(即其子女结点)有直接关系。

基本术语

下面结合图中的树来说明一些基本术语和概念。

树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第1张图片
  • 考虑结点 K {\rm K} K 。根 A {\rm A} A 到结点 K {\rm K} K 的唯一路径上的任意结点,称为结点 K {\rm K} K祖先。如结点 {\rm } B {\rm B} B 是结点 K {\rm K} K 的祖先,而结点 K {\rm K} K 是结点 B {\rm B} B子孙。路径上最接近结点 K {\rm K} K 的结点 E {\rm E} E 称为 K {\rm K} K双亲,而 K {\rm K} K 为结点 E {\rm E} E孩子。根 A {\rm A} A 是树中唯一没有双亲的结点。有相同双亲的结点称为兄弟,如结点 K {\rm K} K 和结点 L {\rm L} L 有相同的双亲 E {\rm E} E ,即 K {\rm K} K L {\rm L} L 为兄弟。
  • 树中一个结点的孩子个数称为该结点的度,树中结点的最大度数称为树的度。如结点 B {\rm B} B 的度为2,结点 D {\rm D} D 的度为3,树的度为3。
  • 度大于0的结点称为分支结点(又称非终端结点);度为0 (没有子女结点)的结点称为叶子结点(又称终端结点)。在分支结点中,每个结点的分支数就是该结点的度。
  • 结点的深度、高度和层次。
    结点的层次从树根开始定义,根结点为第1层,它的子结点为第2层,以此类推。双亲在同一层的结点互为堂兄弟,图中结点 G {\rm G} G E , F , H , I , J {\rm E,F,H,I,J} E,F,H,I,J 互为堂兄弟。
    结点的深度是从根结点开始自顶向下逐层累加的。
    结点的高度是从叶结点开始自底向上逐层累加的。
    树的高度(或深度)是树中结点的最大层数。图中树的高度为4。
  • 有序树无序树。树中结点的各子树从左到右是有次序的,不能互换,称该树为有序树, 否则称为无序树。假设上图为有序树,若将子结点位置互换,则变成一棵不同的树。
  • 路径和路径长度。树中两个结点之间的路径是由这两个结点之间所经过的结点序列构成的,而路径长度是路径上所经过的边的个数。
    注意:由于树中的分支是有向的,即从双亲指向孩子,所以树中的路径是从上向下的,同一双亲的两个孩子之间不存在路径。
  • 森林。森林是 m ( m ≥ 0 ) {\rm m(m \ge 0)} m(m0)棵互不相交的树的集合。森林的概念与树的概念十分相近,因为只要把树的根结点删去就成了森林。反之,只要给加 m {\rm m} m 棵独立的树加上一个结点,并把这 m {\rm m} m 棵树作为该结点的子树,则森林就变成了树。如下图所示,该森林拥有3棵树。
树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第2张图片
拥有3棵树的森林

树的性质

树具有如下最基本的性质:

  • 树中的结点数等于所有结点的度数之和加1。
  • 度为 m {\rm m} m 的树中第 i {\rm i} i 层上至多有 m i − 1 {\rm m^{i-1}} mi1 个结点 i ≥ 1 {\rm i \ge 1} i1
  • 高度为 h {\rm h} h m {\rm m} m 叉树至多有 ( m h − 1 ) / ( m − 1 ) {\rm (m^h-1)/(m-1)} (mh1)/(m1) 个结点(第1项为1,公比为 m {\rm m} m 的等比数列求和)。
  • 具有 n {\rm n} n 个结点的 m {\rm m} m 叉树的最小高度为 ⌈ log ⁡ m ( n ( m − 1 ) + 1 ⌉ {\left \lceil \log_{m}{(n(m-1)} +1 \right \rceil } logm(n(m1)+1

二叉树的概念

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

1.二叉树的定义

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

与树相似,二叉树也以递归的形式定义。二叉树是 n ( n ≥ 0 ) {\rm n (n \ge 0)} n(n0) 个结点的有限集合:

  • 或者为空二叉树,即 n = 0 {n=0} n=0
  • 或者由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一棵二叉树。

二叉树是有序树,若将其左、右子树颠倒,则成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。二叉树的5种基本形态如下图所示。

树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第3张图片
二叉树的5种基本形态

二叉树与度为2的有序树的区别:

  • 度为2的树至少有3个结点,而二叉树可以为空。
  • 度为2的有序树的孩子的左右次序是相对于另一孩子而言的,若某个结点只有一个孩子,则这个孩子就无须区分其左右次序,而二叉树无论其孩子数是否为2,均需确定其左右次序,即二叉树的结点次序不是相对于另一结点而言,而是确定的。

2.几个特殊的二叉树

树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第4张图片

  • 满二叉树。一棵高度为 h {\rm h} h,且含有 2 h − 1 {\rm 2^h-1} 2h1 个结点的二叉树称为满二叉树,即树中的每层都含有最多的结点,如图(a)所示。满二叉树的叶子结点都集中在二叉树的最下一层,并且除叶子结点之外的每个结点度数均为2。
    可以对满二叉树按层序编号:约定编号从根结点(根结点编号为1)起,自上而下,自左向右。这样,每个结点对应一个编号,对于编号为 i {\rm i} i 的结点,若有双亲,则其双亲为 ⌊ i / 2 ⌋ {\rm \left \lfloor i/2 \right \rfloor } i/2。 若有左孩子,则左孩子为 2 i {\rm 2i} 2i ;若有右孩子,则右孩子为 2 i + 1 {\rm 2i+1} 2i+1
  • 完全二叉树。高度为 h {\rm h} h 、有 n {\rm n} n 个结点的二叉树,当且仅当其每个结点都与高度为 h {\rm h} h 的满二叉树中编号为 1 ∼ n {\rm 1 \sim n} 1n 的结点一一对应时,称为完全二叉树,如图(b)所示。其特点如下:
    • i ≤ ⌊ n / 2 ⌋ {\rm i\le \left \lfloor n/2 \right \rfloor } in/2 ,则结点 i {\rm i} i 为分支结点,否则为叶子结点。
    • 叶子结点只可能在层次最大的两层上出现。对于最大层次中的叶子结点,都依次排列在该层最左边的位置上
    • 若有度为1的结点,则只可能有一个,且该结点只有左孩子而无右孩子(重要特征)。
    • 按层序编号后,一旦出现某结点(编号为 i {\rm i} i )为叶子结点或只有左孩子,则编号大于 i {\rm i} i 的结点均为叶子结点。
    • n {\rm n} n 为奇数,则每个分支结点都有左孩子和右孩子;若 n {\rm n} n 为偶数,则编号最大的分支结点(编号为 n / 2 {\rm n/2} n/2 )只有左孩子,没有右孩子,其余分支结点左、右孩子都有。
  • 二叉排序树。左子树上所有结点的关键字均小于根结点的关键字;右子树上的所有结点的关键字均大于根结点的关键字;左子树和右子树又各是一棵二叉排序树。
  • 平衡二叉树。树上任一结点的左子树和右子树的深度之差不超过1。

3.二叉树的性质

  • 非空二叉树上的叶子结点数等于度为 2 的结点数加 1 ,即 n 0 = n 2 + 1 {\rm n_0=n_2+1} n0=n2+1
    证明:设度为 0, 1 和 2 的结点个数分别为 n 0 , n 1 , n 2 {\rm n_0,n_1,n_2} n0,n1,n2 ,结点总数 n = n 0 + n 1 + n 2 {\rm n=n_0+n_1+n_2} n=n0+n1+n2 。 再看二叉树中的分支数,除根结点外,其余结点都有一个分支进入,设 B {\rm B} B 为分支总数, 则 n = B + 1 {\rm n=B+1} n=B+1 。由于这些分支是由度为 1 或 2 的结点射出的,所以又有 B = n 1 + 2 n 2 {\rm B=n_1+2n_2} B=n1+2n2 。于是得 n 0 + n 1 + n 2 = n 1 + 2 n 2 + 1 {\rm n_0+n_1+n_2=n_1+2n_2+1} n0+n1+n2=n1+2n2+1 ,则 n 0 = n 2 + 1 {\rm n_0=n_2+1} n0=n2+1
  • 非空二叉树上第 k {\rm k} k 层上至多有 2 k − 1 {\rm 2^{k-1}} 2k1 个结点 ( k ≥ 1 ) {\rm (k \ge 1)} (k1)
    第 1 层至多有 2 1 − 1 = 1 {\rm 2^{1-1}=1} 211=1 个结点(根),第 2 层至多有 2 2 − 1 = 2 {\rm 2^{2-1}=2} 221=2 个结点,以此类推,可以证明其为一个公比为 2 的等比数列 2 k − 1 {\rm 2^{k-1}} 2k1
  • 高度为 h {\rm h} h 的二叉树至多有 2 h − 1 {\rm 2^h-1} 2h1 个结点 ( h ≥ 1 ) {\rm (h \ge 1)} (h1)
    该结论利用上一个性质求前 h {\rm h} h 项的和,即等比数列求和的结果
  • 完全二叉树按从上到下、从左到右的顺序依次编号 1 , 2 , … , n {\rm 1,2,\dots,n} 1,2,,n ,则有以下关系:
    • i > 1 {\rm i>1} i>1 时,结点 i {\rm i} i 的双亲的编号为 $\left \lfloor {\rm i/2} \right \rfloor $ ,即当 i {\rm i} i 为偶数时,其双亲的编号为 i / 2 {\rm i/2} i/2 ,它是双亲的左孩子;当 i {\rm i} i 为奇数时,其双亲的编号为 ( i − 1 ) / 2 {\rm (i-1)/2} (i1)/2 ,它是双亲的右孩子。
    • 2 i ≤ n {\rm 2i \le n} 2in 时,结点 i {\rm i} i 的左孩子编号为 2 i {\rm 2i} 2i ,否则无左孩子。
    • 2 i + 1 ≤ n {\rm 2i+1 \le n} 2i+1n 时,结点 i {\rm i} i 的右孩子编号为 2 i + 1 {\rm 2i+1} 2i+1 ,否则无右孩子。
    • 结点 i {\rm i} i 所在层次(深度)为 ⌊ log ⁡ 2 i ⌋ + 1 {\rm \left \lfloor {\rm \log_{2}{i} } \right \rfloor +1} log2i+1
  • 具有 n {\rm n} n ( n > 0 ) {\rm (n>0)} (n>0) 个结点的完全二叉树的高度为 ⌈ log ⁡ 2 ( n + 1 ) ⌉ {\rm \left \lceil \log_{2}{(n+1)} \right \rceil } log2(n+1) ⌊ log ⁡ 2 n ⌋ + 1 {\rm \left \lfloor \log_{2}{n} \right \rfloor + 1 } log2n+1

二叉树的存储结构

1.顺序存储结构:

二叉树的顺序存储是指用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为 i {\rm i} i 的结点元素存储在一维数组下标为 i {\rm i} i 的分量中。

依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映结点之间的逻辑关系,这样既能最大可能地节省存储空间,又能利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。

但对于一般的二叉树,为了让数组下标能反映二叉树中结点之间的逻辑关系,只能添加一些并不存在的空结点,让其每个结点与完全二叉树上的结点相对照,再存储到一维数组的相应分量中。然而,在最坏情况下,一个高度为 h {\rm h} h 且只有 h {\rm h} h 个结点的单支树却需要占据近 2 h − 1 {\rm 2^h-1} 2h1 个存储单元。二叉树的顺序存储结构如下图所示,其中0表示并不存在的空结点。

二叉树的顺序存储结构建议从数组下标1开始存储树中的结点

普通二叉树先转换成完全二叉树:

树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第5张图片

转换后的二叉树存储状态如下表:

结点值 1 2 3 0 4 0 5 0 0 6
数组索引 0 1 2 3 4 5 6 7 8 9 10

2.链式存储结构:

由于顺序存储的空间利用率较低,因此二叉树一般都采用链式存储结构,用链表结点来存储二叉树中的每个结点。在二叉树中,结点结构通常包括若干数据域和若干指针域,二叉链表至少包含3个域:数据域data、 **左指针域lchild**和右指针域rchild,如下图所示:

image-20220711175617386

下图所示为常用的二叉链表的存储结构。而实际上在不同的应用中,还可以增加某些指针域,如增加指向父结点的指针后,变为三叉链表的存储结构。

树与二叉树的定义,基本术语,性质,二叉树的顺序存储结构,链式存储结构详解_第6张图片
二叉链表的存储结构

二叉树的链式存储结构描述如下:

template<typename T>
struct BiTNode {
    T data;                     //数据域
    BiTNode *lchild, *rchild;   //左、右孩子指针
};

使用不同的存储结构时,实现二叉树操作的算法也会不同,因此要根据实际应用场合(二叉树的形态和需要进行的运算)来选择合适的存储结构。

容易验证,在含有 n {\rm n} n 个结点的二叉链表中,含有 n + 1 {\rm n+1} n+1 个空指针域(重要结论)

证明: n {\rm n} n 个结点的二叉链表共有 2 n {\rm 2n} 2n 个指针域,由于根结点没有直接上层结点,因此在 n {\rm n} n 个结点的二叉链表中只有 n − 1 {\rm n-1} n1 条边,只需要 n − 1 {\rm n-1} n1 个指针域存储这些边,故还剩 n + 1 {\rm n+1} n+1 个空指针域。

你可能感兴趣的:(数据结构笔记,数据结构,c++)