1.28k likes | 1.48k Views
第六章 树和二叉树. 第六章 树和二叉树. 6.1 树的定义和基本概念 6.2 二叉树 6.3 遍历二叉树和线索二叉树 6.4 树和森林 6.5 树与等价问题 6.6 赫夫曼树及其应用. 6.1 树的定义和基本术语. 一、树的定义 树 (Tree) 是 n(n>=0) 个结点的有限集 T , T 为空时称为空树,否则它满足如下两个条件: (1) 有且仅有一个特定的称为根 (Root) 的结点;
E N D
第六章 树和二叉树 6.1 树的定义和基本概念 6.2 二叉树 6.3 遍历二叉树和线索二叉树 6.4 树和森林 6.5 树与等价问题 6.6 赫夫曼树及其应用
6.1树的定义和基本术语 一、树的定义 树(Tree)是n(n>=0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件: (1)有且仅有一个特定的称为根(Root)的结点; (2)其余的结点可分为m(m>=0)个互不相交的子集T1,T2,T3…Tm,其中每个子集又是一棵树,并称其为子树(Subtree)。
A A B C T1 T2 D E F 一、树的定义 说明 1. 数据结构中允许空树存在。 2. 当只有一个结点时,树的结点为根(root). 3. 当n>1时,其余的结点可分为互不相交的子树。 A (a)空树 (b) n=1的树 (c) n>1 的树
二、树的几个基本术语 • 结点的度 树中每个结点具有的子树数或者后继结点数称为该结点的度。 • 树的度 树中所有结点的度的最大值称为该树的度。 • 叶子(终端结点) 度为零的结点。 • 分支结点(非终端结点) 度不为零的结点。 • 儿子 一个结点的后继结点称为该结点的儿子。 • 父亲 一个结点称为其后继结点的父亲。 • 子孙 一个结点的所有子树中的结点称为该结点的子孙。 • 祖先 从根结点到达一个结点的路径上通过的所有结点称为该结点的祖先。
二、树的几个基本术语 兄弟 同一个父结点的结点。 堂兄弟 其父亲在同一层上的结点。 结点的层次 从跟结点开始定义 深度 树中结点的最大层数称为树的层数或高度。 有序树 若从树中的结点的各子树看成是从左到右(不可互换)有序的,则称为有序树。否则称为无序树。 森林0个或多个不相交的树的集合称为森林。
A B H C E I F J G K D
三、树的基本运算 • 求一个父结点。 • 求一个结点的第i个子结点。 • 创建一棵树。 • 插入一棵树。 • 删除一棵树。 • 遍历树。
四、树的四种表示 • 树形表示 • 文氏图表示 • 凹入表表示 • 嵌套括号表示 • 例 一棵具有如下逻辑结构的树 T=(K,V) K={a, b, c, d, e, f, g, h, i, j} V={<a, b>, <a, c>, <b, d>, <b, e>, <b, f>, <c, g>, <c, h>, <e, i>, <e, j> }
b c g h d e f J I 例一棵具有如下逻辑结构的树 T=(K,V) K={ a, b, c, d, e, f, g, h, i, j } V={ <a, b>, <a, c>, <b, d>, <b, e>, <b, f>, <c, g>, <c, h>, <e, i>, <e, j> } • 树形表示 a
a b c g h d e f j i 例一棵具有如下逻辑结构的树 T=(K,V) K={ a, b, c, d, e, f, g, h, i, j } V={ <a, b>, <a, c>, <b, d>, <b, e>, <b, f>, <c, g>, <c, h>, <e, i>, <e, j> } • 文氏图表示 b c a d f h g e i j
a b c g h d e f j i 例一棵具有如下逻辑结构的树 T=(K,V) K={ a, b, c, d, e, f, g, h, i, j } V={ <a, b>, <a, c>, <b, d>, <b, e>, <b, f>, <c, g>, <c, h>, <e, i>, <e, j> } • 凹入表表示 a b d e i j f c g h
a b c g h d e f j i 例一棵具有如下逻辑结构的树 T=(K,V) K={ a, b, c, d, e, f, g, h, i, j } V={ <a, b>, <a, c>, <b, d>, <b, e>, <b, f>, <c, g>, <c, h>, <e, i>, <e, j> } • 嵌套括号表示 a ( b ( d, e ( i, j )) , c (g, h))
6.2 二叉树 6.2.1 二叉树的定义 定义:二叉树是 n(n>=0)个结点的有限集合,此集合或是一个空集,或是由一个根结点及分别称为左子树和右子树的互不相交的二叉树组成。 注 二叉树的定义也是递归的,且二叉树可以为空。
A A A B B B C 6.2.1 二叉树的定义二叉树的5种基本形态二叉树结点的子树要区分左子树和右子树,即使只有一棵子树也要进行区分,说明它是左子树,还是右子树。这是二叉树与树的最主要的差别。 A (a) 空二叉树 (b) 根和空的左右子树 (c) 根和左子树 (d) 根和右子树 (e) 根和左右子树
6.2.1 二叉树的定义 二叉树的运算 • 求一个结点的父亲 • 求一个结点的左儿子、右儿子 • 创建一个二叉树 • 插入左子树或右子树 • 遍历二叉树
性质1 在二叉树的第i层上至多有 个结点(i>=1)。 证明(采用归纳法) 当i=1时,只有一个根结点,2i-1=20 =1,命题成立。 现在假定对所有的k,1<=k<i,命题成立,即第k层上至多有2j-2个结点,那么可以证明k=i时命题也成立。由归纳假设可知,第i-1层上至多有2i-2个结点。 由于二叉树每个结点的度最大为2,故在第i层上最大结点数为第i-1层上最大结点数的二倍, 即2×2i-2=2i-1。 命题得到证明。 6.2.2 二叉树的性质
性质2:深度为k的二叉树至多有 个结点(k>=1). 证明: 深度为k的二叉树的最大的结点为二叉树中每层上的最大结点数之和,由性质1得到每层上的最大结点数,: EkI=1(第i层上的最大结点数)= EkI=12i-1=2k–1
设度为1的结点数为n1,二叉树中总结点数为N,因为二叉树中所有结点均小于或等于2,所以有:N=n0+n1+n2 (6-1) 再看二叉树中的分支数,除根结点外,其余结点都有一个进入分支,设B为二叉树中的分支总数,则有:N=B+1。 由于这些分支都是由度为1和2的结点射出的,所以有: B=n1+2*n2 N=B+1=n1+2×n2+1 (6-2) 由式(6-1)和(6-2)得到: n0=n2+1 性质3: 对任何一棵二叉树,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。
1 2 3 4 5 7 6 满二叉树和完全二叉树 一棵深度为k且由2k-1个结点的二叉树称为满二叉树。 满二叉树
1 1 1 2 3 2 3 2 3 4 4 7 5 6 5 7 6 如果深度为k、有n个结点的二叉树中个结点能够与深度为k的顺序编号的满二叉树从1到n标号的结点相对应,则称这样的二叉树为完全二叉树,图6.10(b)(c)是2棵非完全二叉树。满二叉树是完全二叉树的特例。 (a)完全二叉树 ( c)非完全二叉树 (b)非完全二叉树
完全二叉树的特点 (1)所有的叶结点都出现在第k层或k-1层。 (2)对任一结点,如果其右子树的最大层次为1,则其左子树的最大层次为1或l+1。
1 2 3 4 5 6 性质4:具有n个结点的完全二叉树的深度为[log2n]+1。 • 符号[x]表示不大于x的最大整数。 • 假设此二叉树的深度为k,则根据性质2及完全二叉树的定义得到:2k-1-1<n<=2k-1 或 • 2k-1<=n<2k • 取对数得到:k-1<log2n<k 因为k是整数。所以有:k=[log2n]+1。
性质5: 如果对一棵有n个结点的完全二叉树的结点按层序编号(从第1层到第【log2n】+1层,每层从左到右),则对任一结点i(1<=i<=n),有: (1)如果i=1,则结点i无双亲,是二叉树的根;如果i>1,则其双亲是结点【i/2】。 (2)如果2i>n,则结点i为叶子结点,无左孩子;否则,其左孩子是结点2i。 (3)如果2i+1>n,则结点i无右孩子;否则,其右孩子是结点2i+1。
如图6.11所示为完全二叉树上结点及其 左右儿子结点之间的关系。 [i/2] i i+1 2i 2i+1 2(i+1) 2i+3 (a) i和i+1结点在同一层
i i+1 2i 2i+1 2(i+1) 2i+3 如图6.11所示为完全二叉树上结点及其 左右儿子结点之间的关系。 (b)I和i+1结点不在同一层
在此过程中,可以从(2)和(3)推出(1),所以先证明(2)和(3)。在此过程中,可以从(2)和(3)推出(1),所以先证明(2)和(3)。 对于i=1,由完全二叉树的定义,其左孩子是结点2,若2>n,即不存在结点2,此时,结点i无孩子。结点i的右孩子也只能是结点3,若结点3不存在,即3>n,此时结点i无右孩子。 对于i>1,可分为两种情况: (1)设第j(1<=j<=[log2n])层的第一个结点的编号为i,由二叉树的性质2和定义知i=2j-1结点i的左孩子必定为的j+1层的第一个结点,其编号为2j=2×2j-1=2i。如果2i>n,则无左孩子。
其右孩子必定为第j+1层的第二个结点,编号为2i+1。若2i+1>n,则无右孩子。其右孩子必定为第j+1层的第二个结点,编号为2i+1。若2i+1>n,则无右孩子。 (2)假设第j(1<=j<=[log2n])层上的某个结点编号为i(2e(j-1)<=i<=2ej-1),且2i+1<n,其左孩子为2i,右孩子为2i+1,则编号为i+1的结点时编号为i的结点的右兄弟或堂兄弟。若它有左孩子,则其编号必定为2i+2=2×(i+1):若它有右孩子,则其编号必定为2i+3=2×(i+1)+1。当i=1时,就是根,因此无双亲,当i>1时,如果i为左孩子,即2×(i/2)=i,则i/2是i的双亲;如果i为右孩子,i=2p+1,i的双亲应为p,p=(i-1)/2=[i/2]. 证毕。
6.2.3 二叉树的存储结构 一、 二叉树的顺序存储 二、二叉树的链式存储
一、 二叉树的顺序存储表示 用一组连续的存储单元存储二叉树的结点。 #define Maxsize 100 // 二叉树的最大结点数 typedef TElemType SqBiTree[Maxsize]; // 0号单元存储根结点 SqBiTree bt;
a b c d e f g h i j k l 1. 满二叉树的存储 0 1 2 3 4 5 6 7 8 9 10 11
0 A 2 1 B D 6 4 E C 13 F 2.一般二叉树的存储 0 1 2 3 4 5 6 7 8 9 10 11 12 13 A B D C E F
二、二叉树的链式存储表示 1. 二叉链表 2.三叉链表 3.双亲链表 4.线索链表
lchild data rchild a b c d e f g 1. 二叉链表 结点结构:
A B D E C F root A B D C E F
C 语言的类型描述如下: typedef struct BiTNode { // 结点结构 TElemType data; struct BiTNode *lchild, *rchild; // 左右孩子指针 } BiTNode, *BiTree; 结点结构: lchild data rchild
a lchild dataparent rchild b c d e f g 2. 三叉链表 结点结构:
lchild data parent rchild C 语言的类型描述如下: typedef struct TriTNode { // 结点结构 TElemType data; struct TriTNode *lchild, *rchild; // 左右孩子指针 struct TriTNode *parent; //双亲指针 } TriTNode, *TriTree; 结点结构:
A B D E C A F B D C E F root
一、问题的提出 顺着某一条搜索路径巡访二叉树 中的结点,使得每个结点均被访问一 次,而且仅被访问一次。 “访问”的含义可以很广,如:输出结 点的信息等。
“遍历”是任何类型均有的操作,对线性结构而言,只有一条搜索路径(因为每个结点均只有一个后继),故不需要另加讨论。 而二叉树是非线性结构,每个结点有两个后继,则存在如何遍历即按什么样的搜索路径遍历的问题。
二、遍历算法 • TLR前序的遍历算法 • LTR中序的遍历算法 • LRT后序的遍历算法 • 层次遍历算法
A T1 T2 前(根)序TLR的遍历算法: 若二叉树为空树,则空操作;否则, (1)访问根结点; (2)先序遍历左子树; (3)先序遍历右子树。
A T1 T2 中(根)序的遍历算法: 若二叉树为空树,则空操作;否则, (1)中序遍历左子树; (2)访问根结点; (3)中序遍历右子树。
A T1 T2 后(根)序的遍历算法: 若二叉树为空树,则空操作;否则, (1)后序遍历左子树; (2)后序遍历右子树; (3)访问根结点。
三、算法的递归描述 void PreOrderTraverse ( BiTree T) { // 先序遍历二叉树 if ( T ) { visit(T->data); // 访问结点 PreOrderTraverse( T->lchild ); // 遍历左子树 PreOrderTraverse( T->rchild ); // 遍历右子树 } }
三、算法的递归描述 void InOrderTraverse ( BiTree T) { // 中序遍历二叉树 if ( T ) { InOrderTraverse( T->lchild ); // 遍历左子树 visit(T->data); // 访问结点 InOrderTraverse( T->rchild ); // 遍历右子树 } }
三、算法的递归描述 void PostOrderTraverse ( BiTree T) { // 后序遍历二叉树 if ( T ) { PostOrderTraverse( T->lchild ); // 遍历左子树 PostOrderTraverse( T->rchild ); // 遍历右子树 visit(T->data); // 访问结点 } }