数据结构 第六章树和二叉树

48
数数数数 数数 中中中中中中中中中中中中 中中中中中中中中中中中中 数数数数 数数数数 数数数 数数数 数数数数数 数数数数数

description

数据结构 第六章树和二叉树. 本章内容 6.1 树的概念与基本术语 6.2 二叉树 6.3 遍历二叉树 6.4 线索二叉树 6.5 树与森林 6.6 赫夫曼树及其应用. A. B. C. D. E. F. G. H. I. J. M. K. L. A. 只有根结点的树. 有 13 个结点的树. 6.1 树的概念与基本术语. 树的定义 (Tree) 树是有 n(n≥0) 个结点的有限集合。 如果 n=0 ,称为空树; - PowerPoint PPT Presentation

Transcript of 数据结构 第六章树和二叉树

Page 1: 数据结构 第六章树和二叉树

《 数据结构》课程

中国科学技术大学网络学院中国科学技术大学网络学院

数据结构数据结构第六章第六章 树和二叉树树和二叉树

Page 2: 数据结构 第六章树和二叉树

本章内容6.1 树的概念与基本术语6.2 二叉树6.3 遍历二叉树6.4 线索二叉树6.5 树与森林6.6 6.6 赫夫曼树及其应用

Page 3: 数据结构 第六章树和二叉树

6-3 中国科大《数据结构》

6.1 树的概念与基本术语 树的定义 (Tree)

树是有 n(n≥0) 个结点的有限集合。 如果 n=0 ,称为空树; 如果 n>0, 称为非空树 , 对于非空树 , 有且仅有一个特定的称为根 (Root)的节点 ( 无直接前驱 ) 如果 n>1 ,则除根以外的其它结点划分为 m (m>0) 个互不相交的有限集 T1, T2 ,…, Tm ,其中每个集合本身又是一棵树,并且称为根的子树(SubTree) 。 每个结点都有唯一的直接前驱,但可能有多个后继

树的举例 其中: A 是根;其余结点分成三个互不相交的子集, T1={B,E,F,K,L} ; T2={C,G} ; T3={D,H,I,J,M}, T1,T2,T3 都是根 A 的子树,且本身也是一棵树

A

C

G

B D

E F

K L

H

M

I J

有 13 个结点的树

A只有根结点的树

Page 4: 数据结构 第六章树和二叉树

6-4 中国科大《数据结构》

6.1 树的概念与基本术语 树的基本术语

结点:包含一个数据元素及若干指向其子树的分支 结点的度:结点拥有的子树数 , 或者说后继结点数 叶结点:度为 0 的结点 [ 没有子树的结点 ] 分支结点:度不为 0 的结点 [ 包括根结点 ] , 也称为非终端结点。 内部结点 : 除根外的结点 孩子:结点的子树的根 双亲:孩子的直接前驱

A

B C D

E F G H I J

K L M

1层2层

4层3层

Height= 4

Page 5: 数据结构 第六章树和二叉树

6-5 中国科大《数据结构》

6.1 树的概念与基本术语 兄弟:同一双亲的孩子 子孙:以某结点为根的 树中的所有结点 祖先:从根到该结点 所经分支上的所有结点 层次:根结点为第一层,其孩子为第二层,依此类推 深度:树中结点的最大层次 森林:互不相交的树的集合。对树中每个结点而言,其子树的

集合即为森林

A

B C D

E F G H I J

K L M

1层2层

4层3层

Height= 4

Page 6: 数据结构 第六章树和二叉树

6-6 中国科大《数据结构》

6.2 二叉树 二叉树 (Binary Tree)

每个结点最多有2棵子树 二叉树的子树有左右之分

RR LL

空树   只有根   只有左子树  只有右子树   有左右子树

Page 7: 数据结构 第六章树和二叉树

6-7 中国科大《数据结构》

6.2 二叉树 二叉树性质1:在二叉树的第 i 层上至多有 2i-1 个结点

证明:1. i=1, 只有一个根节点,因此 2i-1=20=12. 设第 i-1 层上,以上性质成立,即第 i-1 层至多有 2(i-1)-1 结

点。3. 由二叉树的定义可知,任何结点的度小于 2 ,因此,第 i

层上的结点数最多为第 i-1 层上的两倍,即 2*2i-2=2i-1

证毕

Page 8: 数据结构 第六章树和二叉树

6-8 中国科大《数据结构》

6.2 二叉树 二叉树性质2:深度为 k 的二叉树至多有 2k-1 个结点

证明:1. 由性质1,已知第 i 层上结点数最多为 2i-12. k ∑ 2i-1 = 2k-1 i=1证毕

Page 9: 数据结构 第六章树和二叉树

6-9 中国科大《数据结构》

6.2 二叉树 二叉树性质3:如果二叉树终端结点数为 n0 ,度为 2 的结点数为

n2 ,则 n0=n2+1证明:

1. 设 n1 是度为 1 的结点,则总结点数 n= n0+n1+n22. 设 B 为二叉树的分支数,除根结点外,每个结点有且只有

一个分支,因此 n=B+13. 每个分支皆由度为 1 或 2 的结点发出, B=n1+2n24. n=B+1=(n1+2n2)+1 = n0+n1+n2 ,因此 n0=n2+1

证毕

Page 10: 数据结构 第六章树和二叉树

6-10 中国科大《数据结构》

6.2 二叉树 满二叉树:

一个深度为 k 且有 2k-1 个结点的二叉树 每层上的结点数都是最大数 可以自上而下、自左至右连续编号

8 9 10 11 12 13 14 15

4 5 6 7

2 3

1

Page 11: 数据结构 第六章树和二叉树

6-11 中国科大《数据结构》

6.2 二叉树 完全二叉树:

当且仅当每一个结点都与深度相同的满二叉树中编号从 1 到 n的结点一一对应的二叉树

叶子结点只在最大两层上出现 左子树深度与右子树深度相等或大1

8 9 10 11 12

4 5 6 7

2 3

1

Page 12: 数据结构 第六章树和二叉树

6-12 中国科大《数据结构》

6.2 二叉树 完全二叉树 ( 性质4 ) :具有 n 个结点的完全二叉树 , 其深度为 log2n +1证明:设 k 为深度,由二叉树性质2,已知

   2k-1-1 < n ≤ 2k-1即  2k-1 ≤ n < 2k

即 k = log2n +1

8 9 10 11 12

4 5 6 7

2 3

1

x : 表示向下取整,值为 不大于 x 的最大整数

Page 13: 数据结构 第六章树和二叉树

6-13 中国科大《数据结构》

完全二叉树 ( 性质5 ) : 在完全二叉树中,结点 i 的双亲为 i/2 结点 i 的左孩子 LCHILD(i)=2i 结点 i 的右孩子 RCHILD(i)=2i+1

6.2 二叉树

8 9 10 11 12

4 5 6 7

2 3

1

2i 2i+1 2i+2 2i+3

i i+1

i/2

8 9 10 11 12

4 5 6 7

2 3

1

Page 14: 数据结构 第六章树和二叉树

6-14 中国科大《数据结构》

6.2 二叉树 二叉树的存储结构

1.顺序存储结构2.链式存储结构

顺序存储结构:用一个一维数组来存储二叉树的各个结点 C 语言表示#define MAX_TREE_SIZE 100 // 二叉树的最大结点数typedef TElemType SqBiTree[MAX_TREE_SIZE];//0 号单元存储根结点SqBiTree bt; 显然,二叉树的结点必须按某种次序分别存入数组的各个单元,这种次序应能反映结点间的逻辑关系,否则二叉树上的各种基本运算在顺序存储结构上很难实现。 对于完全二叉树来说,可以采用“以编号为地址”的方法,将编号为 i 的结点存入一维数组的第 i 个单元 ( 下标为 i-1) 。

Page 15: 数据结构 第六章树和二叉树

6-15 中国科大《数据结构》

6.2 二叉树 完全二叉树的顺序表示

例 :

对应的顺序存储结构 :将编号为 i 的结点存入一维数组的第 i 个单元 ( 下标为 i-1)

8 9 10

4 5 6 7

2 3

1

9876543210

10987654321下标→

Page 16: 数据结构 第六章树和二叉树

6-16 中国科大《数据结构》

非完全二叉树的顺序表示非完全二叉树的顺序表示例例 ::

对应的顺序存储结构对应的顺序存储结构 ::一维数组的一维数组的 2121单元中只用上了单元中只用上了 77个个 .. 最坏情况下最坏情况下 ,, 一个深度为一个深度为 kk 且只有且只有 kk 个个结点的单支树结点的单支树 ,,却需要长度为却需要长度为 22kk-1-1 的一维数组的一维数组

总结总结 顺序存储结构适合存储完全二叉树顺序存储结构适合存储完全二叉树 对于非完全二叉树,采用链式存储结构更合适对于非完全二叉树,采用链式存储结构更合适

6.2 二叉树

A B D C E G F

D C

B

A

F

E G

Page 17: 数据结构 第六章树和二叉树

6-17 中国科大《数据结构》

6.2 二叉树 二叉链表

结点结构 :通常每个结点中设置三个域 , 即值域、左指针域和右指针域,其结点结构如下:其中 data 表示值域, lchild和 rchild分别表示左指针域和右指针域,用以分别存储指向左儿子结点和右儿子结点的指针。

TElemType 可以是任何相应的数据类型如 int 、 float 或 char 等。

lchild data rchild

typedef struct BiTNode{ TElemType data; struct BiTNode *lchild, *rchild; } BiTNode, *BITree;

Page 18: 数据结构 第六章树和二叉树

6-18 中国科大《数据结构》

6.2 二叉树

F

E C

D C

B

A A ^

B

^ D ^ C

^ E ^ G ^

^ F ^链式存储示例节点

Page 19: 数据结构 第六章树和二叉树

6-19 中国科大《数据结构》

6.2 二叉树 三叉链表三叉链表

通常每个结点中设置四个域通常每个结点中设置四个域 ,, 即值域、左指针域、右指针即值域、左指针域、右指针域和双亲指针域,其结点结构如下:域和双亲指针域,其结点结构如下:

其中其中 datadata 表示值域,用于存储放入结点的数据,表示值域,用于存储放入结点的数据, lchildlchild和和 rchildrchild 分别表示左指针域和右指针域,用以分别存储指向左儿子分别表示左指针域和右指针域,用以分别存储指向左儿子结点和右儿子结点的指针结点和右儿子结点的指针 ,parent,parent 指向双亲结点。指向双亲结点。

lchild data parent rchild

Page 20: 数据结构 第六章树和二叉树

6-20 中国科大《数据结构》

6.3 遍历二叉树 遍历二叉树遍历二叉树

定义:二叉树的遍历定义:二叉树的遍历 (Traverse)(Traverse) 是指按一定的规律访问二叉是指按一定的规律访问二叉树的每个结点,且每个结点只被访问一次的过程。树的每个结点,且每个结点只被访问一次的过程。

对二叉树的遍历过程实际上是将非线性结构的二叉树中的结点对二叉树的遍历过程实际上是将非线性结构的二叉树中的结点排列成一个线性序列的过程。排列成一个线性序列的过程。

本节仅讨论二叉链表的遍历过程。设访问根结点用本节仅讨论二叉链表的遍历过程。设访问根结点用 DD 表示,遍表示,遍历左、右子树用历左、右子树用 LL 、、 RR 表示表示

遍历分类:在任一结点上,有三种执行操作:访问结点本身,遍历遍历分类:在任一结点上,有三种执行操作:访问结点本身,遍历该结点左子树,遍历该结点右子树。操作次序主要分为三种:该结点左子树,遍历该结点右子树。操作次序主要分为三种:

1.1. 左、根、右;也称为左、根、右;也称为中序遍历、中序遍历、 LDRLDR ;;2.2. 根、左、右;也称为根、左、右;也称为先序遍历、先序遍历、 DLRDLR ;;3.3. 左、右、根;也称为左、右、根;也称为后序遍历、后序遍历、 LRDLRD 。。

Page 21: 数据结构 第六章树和二叉树

6-21 中国科大《数据结构》

6.3 遍历二叉树 三种遍历次序以递归的形式定义三种遍历次序以递归的形式定义

1.1. 中序中序 (InOrder)(InOrder) 遍历:若树为空,执行空操作;否则依次执行:遍历:若树为空,执行空操作;否则依次执行: 中序遍历左子树中序遍历左子树 LL ;; 访问根结点访问根结点 DD ;; 中序遍历右子树中序遍历右子树 RR 。。

2.2. 先序先序 (PreOrder)(PreOrder) 遍历:若树为空,执行空操作;否则依次执行:遍历:若树为空,执行空操作;否则依次执行: 访问根结点访问根结点 DD ;; 先序遍历左子树先序遍历左子树 LL ;; 先序遍历右子树先序遍历右子树 RR 。。

3.3. 后序后序 (PostOrder)(PostOrder) 遍历:若树为空,执行空操作;否则依次执行:遍历:若树为空,执行空操作;否则依次执行: 后序遍历左子树后序遍历左子树 LL ;; 后序遍历右子树后序遍历右子树 RR ;; 访问根结点访问根结点 DD 。。

Page 22: 数据结构 第六章树和二叉树

6-22 中国科大《数据结构》

6.3 遍历二叉树 二叉树遍历的实现

template <class T>void PreOrder(BiTreeNode<T> *t, void Visit(T item))// 使用 Visit(item)函数前序遍历二叉树 t{ if(t != NULL)

{ Visit(t->data); PreOrder(t->Left(), Visit); PreOrder(t->Right(), Visit);

} }

为了通用性,把访问操作设计成前序遍历二叉树函数的一个函数虚参 Visit() 。

A

DB

FC

GE

输出结果: ABDEGCF( 第一个输出节点必为根节点 )

Page 23: 数据结构 第六章树和二叉树

6-23 中国科大《数据结构》

6.3 遍历二叉树template <class T>void InOrder(BiTreeNode<T> *t, void Visit(T item))//使用 Visit(item)函数中序遍历二叉树 t{ if(t != NULL)

{ InOrder(t->Left(), Visit);Visit(t->data);InOrder(t->Right(), Visit);

}}

输出结果: DBGEAFC(先于根节点 A输出的节点为左子树的节点 后于根节点 A输出的节点为右子树的节点)

A

D

B

F

C

G

E

Page 24: 数据结构 第六章树和二叉树

6-24 中国科大《数据结构》

6.3 遍历二叉树template <class T>void PostOrder(BiTreeNode<T> *t, void Visit(T item))//使用 Visit(item)函数后序遍历二叉树 t{ if(t != NULL)

{ PostOrder(t->Left(), Visit);PostOrder(t->Right(), Visit);Visit(t->data);

}}

输出结果: DGEBFCA( 最后一个输出节点必为根节点 )

A

D

B

F

C

G

E

Page 25: 数据结构 第六章树和二叉树

6-25 中国科大《数据结构》

6.3 遍历二叉树 遍历二叉树应用遍历二叉树应用

1.1. 利用后序求结点个数或树的高度利用后序求结点个数或树的高度2.2. 利用前序实现二叉树复制利用前序实现二叉树复制3.3. 判断两棵树是否相等判断两棵树是否相等1.1. Return 1+Size (t->lchild) + Size (t->rchild);Return 1+Size (t->lchild) + Size (t->rchild);2.2. temp->data=progmpde ->data;temp->data=progmpde ->data; temp ->lchile =copy(orignode->lchild);temp ->lchile =copy(orignode->lchild); temp ->rchile =copy(orignode->rchild);temp ->rchile =copy(orignode->rchild);3.3. If (a!=NULL && b!=NULL && a->data=b->data If (a!=NULL && b!=NULL && a->data=b->data && equal(a->lchild=b-> lchild) && equal(a->lchild=b-> lchild) && equal(a->rchild=b-> rchild))&& equal(a->rchild=b-> rchild))

Page 26: 数据结构 第六章树和二叉树

6-26 中国科大《数据结构》

6.3 遍历二叉树 根据先、中序遍历求序列二叉树根据先、中序遍历求序列二叉树:如果已知一棵二叉树的先序遍历:如果已知一棵二叉树的先序遍历和中序遍历序列,则可以惟一确定这棵二叉树和中序遍历序列,则可以惟一确定这棵二叉树

算法:算法:1.1. 在先序遍历序列中,第一个节点为根节点在先序遍历序列中,第一个节点为根节点 DD2.2. 在中序遍历序列中,根节点在中序遍历序列中,根节点 DD 左边的节点归为左子树,根节点左边的节点归为左子树,根节点

DD 右边的节点归为右子树右边的节点归为右子树3.3. 对每个子树反复使用对每个子树反复使用 1,21,2 两步,直到确定二叉树两步,直到确定二叉树

Page 27: 数据结构 第六章树和二叉树

6-27 中国科大《数据结构》

6.3 遍历二叉树 示例:已知一棵二叉树的示例:已知一棵二叉树的

先序遍历序列为:先序遍历序列为: ABDEGCFABDEGCF ,, 中序遍历序列为:中序遍历序列为: DBGEAFCDBGEAFC ,,请画出这棵二叉树请画出这棵二叉树

解:根据先序遍历序列,可知根节点为解:根据先序遍历序列,可知根节点为 AA ;再根据中序遍历序列可;再根据中序遍历序列可知,左子树由知,左子树由 DBGEDBGE 组成,右子树由组成,右子树由 FCFC 组成。组成。重复上述步骤,分别求出左子树和重复上述步骤,分别求出左子树和右子树的细节。右子树的细节。

27

A

DB

F

C

G

E左子树 右子树

Page 28: 数据结构 第六章树和二叉树

6-28 中国科大《数据结构》

6.3 遍历二叉树 根据后、中序遍历求序列二叉树根据后、中序遍历求序列二叉树:如果已知一棵二叉树的后序遍历:如果已知一棵二叉树的后序遍历和中序遍历序列,则可以惟一确定这棵二叉树和中序遍历序列,则可以惟一确定这棵二叉树

算法:算法:1.1. 在后序遍历序列中,最后一个节点为根节点在后序遍历序列中,最后一个节点为根节点 DD2.2. 在中序遍历序列中,根节点在中序遍历序列中,根节点 DD 左边的节点归为左子树,根节点左边的节点归为左子树,根节点

DD 右边的节点归为右子树右边的节点归为右子树3.3. 对每个子树反复使用对每个子树反复使用 1,21,2 两步,直到确定二叉树两步,直到确定二叉树

Page 29: 数据结构 第六章树和二叉树

6-29 中国科大《数据结构》

6.3 遍历二叉树 示例:已知一棵二叉树的示例:已知一棵二叉树的

后序遍历序列为:后序遍历序列为: DGEBFCA DGEBFCA ,, 中序遍历序列为:中序遍历序列为: DBGEAFCDBGEAFC ,,请画出这棵二叉树请画出这棵二叉树

解:根据后序遍历序列,可知根节点为解:根据后序遍历序列,可知根节点为 AA ;再根据中序遍历序列可;再根据中序遍历序列可知,左子树由知,左子树由 DBGEDBGE 组成,右子树由组成,右子树由 FCFC 组成。组成。重复上述步骤,分别求出左子树和重复上述步骤,分别求出左子树和右子树的细节。右子树的细节。

29

A

DB

F

C

G

E左子树 右子树

Page 30: 数据结构 第六章树和二叉树

6-30 中国科大《数据结构》

6.4 线索二叉树 二叉树以二叉链表存储结构不足二叉树以二叉链表存储结构不足

所有叶子结点与无子结点的结点指针位置,存储结构都是空的;所有叶子结点与无子结点的结点指针位置,存储结构都是空的; 同时只能找到结点的左右孩子的信息同时只能找到结点的左右孩子的信息 ,, 而不能在结点的任一序而不能在结点的任一序列的列的前驱前驱与与后继后继信息信息 ,,这种信息只有在遍历的动态过程中才能这种信息只有在遍历的动态过程中才能得到。得到。

解决办法解决办法利用二叉树中得空位置,建立遍历指针,达到在遍历中不利用二叉树中得空位置,建立遍历指针,达到在遍历中不

再使用堆栈的目的。遍历指针被称为:再使用堆栈的目的。遍历指针被称为:线索。线索。带有线索的二叉树被带有线索的二叉树被称为:称为:线索二叉树线索二叉树

a

c d^̂

f ^̂^̂ g ^̂^̂ h ^̂^̂

Page 31: 数据结构 第六章树和二叉树

6-31 中国科大《数据结构》

6.4 线索二叉树 在中序遍历过程中,遇到空指针时,需要决定遍历的后续结点的位置,所以: 空的右指针空的右指针指向遍历后继指向遍历后继 空的左指针空的左指针指向遍历前趋指向遍历前趋

a

c d

f^̂ g h ^̂后继指针前趋指针

Page 32: 数据结构 第六章树和二叉树

6-32 中国科大《数据结构》

6.4 线索二叉树 线索二叉树中,只有两个空的指针分析中序的遍历过程线索二叉树中,只有两个空的指针分析中序的遍历过程

从左指针为空的结点开始遍历从左指针为空的结点开始遍历 到右指针为空的结点结束遍历到右指针为空的结点结束遍历

建立二叉树的线索建立二叉树的线索:在遍历过程中建立。:在遍历过程中建立。遍历时,记录当前结点的前趋和后继,在遇到空指针时,遍历时,记录当前结点的前趋和后继,在遇到空指针时,

建立相应的连接。建立相应的连接。

Page 33: 数据结构 第六章树和二叉树

6-33 中国科大《数据结构》

6.5 树与森林 树的存储结构树的存储结构1.1. 双亲表示法双亲表示法

采用一组连续的存储空间采用一组连续的存储空间 由于每个结点只有一个双亲,只需要一个指针由于每个结点只有一个双亲,只需要一个指针

0 1 2 3 4 5 6

A B C D E F G

-1 0 0 0 1 1 3

C

E F G

B D

A

Page 34: 数据结构 第六章树和二叉树

6-34 中国科大《数据结构》

6.5 树与森林2. 孩子表示法 [ 多重链表 ]

可以采用多重链表,即每个结点有多个指针

最大缺点是空链域太多  [(d-1)n+1 个 ]

C

E F G

B D

A

childd……child3child2child1data

Page 35: 数据结构 第六章树和二叉树

6-35 中国科大《数据结构》

6.5 树与森林3.3. 孩子表示法孩子表示法 [[单链表单链表 ]]

将每个结点的孩子排列起来,用单链表表示将每个结点的孩子排列起来,用单链表表示 将每个结点排列成一个线性表将每个结点排列成一个线性表

C

E F G

B D

A

GFEDCBA0

123456

Root

2 3 ^5 ^

6 ^

1 ^4 ^

Page 36: 数据结构 第六章树和二叉树

6-36 中国科大《数据结构》

6.5 树与森林4.4. 孩子兄弟表示法孩子兄弟表示法

采用二叉链表采用二叉链表 左边指针指向第一个孩子,右边指针指向兄弟左边指针指向第一个孩子,右边指针指向兄弟

C

E F G

B D

A

data firstChild nextSibling

B

CD

GF

E

A

Page 37: 数据结构 第六章树和二叉树

6-37 中国科大《数据结构》

6.5 树与森林 树与二叉树的对应关系树与二叉树的对应关系

树与二叉树都可以采用二叉链表作存储结构树与二叉树都可以采用二叉链表作存储结构 任意给定一棵树,可以找到一个唯一的二叉树任意给定一棵树,可以找到一个唯一的二叉树 (( 没有右子树没有右子树 ))

树转换为二叉树的方法树转换为二叉树的方法1.1. 树中所有相邻兄弟之间加一条连线。树中所有相邻兄弟之间加一条连线。2.2. 对树中的每个结点,只保留它与第一个孩子结点之间的连线,对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其它孩子结点之间的连线。删去它与其它孩子结点之间的连线。3.3. 以树的根结点为轴心,将整棵树顺时针转动以树的根结点为轴心,将整棵树顺时针转动 454500 ,使之结构层,使之结构层次分明。次分明。

B

CD

GF

E

A

C

E F G

B D

A

CE

F

G

B

D

A

树 对应的二叉树

Page 38: 数据结构 第六章树和二叉树

6-38 中国科大《数据结构》

树转换成二叉树的过程举例 A

B F G

D C E

A

B F G

D C E

A

B F G

D C E

A

B

F

G

D

C E

(a) 一棵树 (b) 连接相邻兄弟

(c)  删除非长子结点的链接 (d) 旋转后的二叉树

6.5 树与森林

Page 39: 数据结构 第六章树和二叉树

6-39 中国科大《数据结构》

6.5 树与森林 森林与二叉树的对应关系森林与二叉树的对应关系

如果把森林中的第二棵树的根结点看作是第一棵树的根结点的兄如果把森林中的第二棵树的根结点看作是第一棵树的根结点的兄弟,则可找到一个唯一的二叉树与之对应。弟,则可找到一个唯一的二叉树与之对应。 森林转换成二叉树森林转换成二叉树

如果如果 F={T1,T2, … , Tm}F={T1,T2, … , Tm} 是森林,按如下规则可转换成一棵二叉是森林,按如下规则可转换成一棵二叉树树 B=(root,LB,RB)B=(root,LB,RB) 。。 (( 11)若)若 FF 为空,则为空,则 BB 为空;为空; (( 22)若)若 FF 非空,则森林中第一棵树非空,则森林中第一棵树 T1T1 的根结点为二叉树的根结点为二叉树 BB 的根结点,的根结点, BB的左子树的左子树 LBLB 由树由树 T1T1 根结点下的子树森林转换而成。右子树根结点下的子树森林转换而成。右子树 RBRB 是由森林是由森林FF 中除树中除树 T1T1 外余下部分转换而成。外余下部分转换而成。

对应的二叉树

F

GC

E

B D

A

JI

K

HT1 T2 T3 F

GC

E

B

D

A

K

H

I J

三棵树的森林

Page 40: 数据结构 第六章树和二叉树

6-40 中国科大《数据结构》

6.5 树与森林 树的遍历树的遍历

对树的遍历主要有两种:先根(次序)遍历、后根(次序)遍历对树的遍历主要有两种:先根(次序)遍历、后根(次序)遍历 先根(次序)遍历:当树非空时先根(次序)遍历:当树非空时

1.1. 访问根结点访问根结点2.2. 依次先根遍历根的各棵子树依次先根遍历根的各棵子树 输出结果:输出结果: ABEFCDGABEFCDG

后根(次序)遍历:当树非空时后根(次序)遍历:当树非空时1.1. 依次后根遍历根的各棵子树依次后根遍历根的各棵子树2.2. 访问根结点访问根结点 输出结果:输出结果: EFBCGDAEFBCGDA

C

E F G

B D

A

Page 41: 数据结构 第六章树和二叉树

6-41 中国科大《数据结构》

6.5 树与森林 与二叉树遍历的关系与二叉树遍历的关系

当采用孩子兄弟表示法表示树时:当采用孩子兄弟表示法表示树时: 树的先根遍历,与树对应的二叉树的先根遍历完全相同树的先根遍历,与树对应的二叉树的先根遍历完全相同 树的后根遍历,与树对应的二叉树的中根遍历完全相同树的后根遍历,与树对应的二叉树的中根遍历完全相同

Page 42: 数据结构 第六章树和二叉树

6-42 中国科大《数据结构》

6.6 赫夫曼树及其应用 赫夫曼树赫夫曼树

赫夫曼树(赫夫曼树( HuffmanHuffman)树也称最优二叉树,是一类带权路径长度最)树也称最优二叉树,是一类带权路径长度最短的树,在判定、查找及数据压缩技术中有着广泛的应用。短的树,在判定、查找及数据压缩技术中有着广泛的应用。

基本术语基本术语 路径路径:从树中一个结点到另一个结点之间的分支构成这两个结点:从树中一个结点到另一个结点之间的分支构成这两个结点

之间的路径之间的路径 路径长度路径长度:路径上的分支数目:路径上的分支数目 树的路径长度树的路径长度:从树根到每个结点的路径长度之和:从树根到每个结点的路径长度之和 带权路径长度带权路径长度:从结点到树根之间的路径长度与结点权的乘积:从结点到树根之间的路径长度与结点权的乘积 树的带权路径长度树的带权路径长度 (WPL)(WPL) :树中所有叶结点的带权路径长度之和:树中所有叶结点的带权路径长度之和 最优二叉树最优二叉树:假设二叉树有:假设二叉树有 nn 个叶子,其每个叶子结点权为个叶子,其每个叶子结点权为 wwii ,,

则带权路径长度则带权路径长度 WPLWPL 最小的二叉树称为最优二叉树。赫夫曼最小的二叉树称为最优二叉树。赫夫曼 (H(Huffman)uffman) 树就是一棵最优二叉树树就是一棵最优二叉树

Page 43: 数据结构 第六章树和二叉树

6-43 中国科大《数据结构》

6.6 赫夫曼树及其应用 例:下图所示的树路径长度为:例:下图所示的树路径长度为: 2*1+3*2+1*3=112*1+3*2+1*3=11

下图所示的树的带权路径长度 下图所示的树的带权路径长度 WPL = 2*5+3*3+2*4=27WPL = 2*5+3*3+2*4=27

A

D

B

F

C

G

E5 4

3

Page 44: 数据结构 第六章树和二叉树

6-44 中国科大《数据结构》

6.6 赫夫曼树及其应用 构造构造 HuffmanHuffman 树树

在在 HuffmanHuffman 树中,权值最大的结点离根最近树中,权值最大的结点离根最近 权值最小的结点离根最远权值最小的结点离根最远

HuffmanHuffman 树算法树算法1.1. 根据给定的根据给定的 nn 个权值个权值 (w(w11, w, w22, …, w, …, wnn))构成构成 nn 棵二叉树的集合棵二叉树的集合 FF

={T={T11, T, T22, …, T, …, Tnn}} ,其中每棵二叉树,其中每棵二叉树 TTii 中只有一个带树为中只有一个带树为 TTii 的根的根结点结点

2.2. 在在 FF 中选取两棵根结点的权值最小的树作为左右子树构造一棵中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置其根结点的权值为其左右子树权值之和新的二叉树,且置其根结点的权值为其左右子树权值之和

3.3. 在在 FF 中删除这两棵树,同时将新得到的二叉树加入中删除这两棵树,同时将新得到的二叉树加入 FF 中中4.4. 重复重复 2, 32, 3 ,直到,直到 FF 只含一棵树为止只含一棵树为止

Page 45: 数据结构 第六章树和二叉树

6-45 中国科大《数据结构》

6.6 赫夫曼树及其应用 构造 Huffman 树示例

F : {7} {5} {2} {4} F : {7} {5} {6}

F : {7} {11}

7 5 2 4

1. 初始2. 合并 {2} {4}

7 5

2 4

6

F : {18} 11

7 5

2 4

6

3. 合并 {5} {6}

5

4. 合并 {7} {11} 2

7

4

6

1118

Page 46: 数据结构 第六章树和二叉树

6-46 中国科大《数据结构》

6.6 赫夫曼树及其应用 HuffmanHuffman 编码编码

设给出一段报文:设给出一段报文: GOOD_GOOD_GOOD_GOOOOOOOOGOOD_GOOD_GOOD_GOOOOOOOO_OFF_OFF ,字符集合是,字符集合是 {O,G,_,D,F}{O,G,_,D,F} ,各个字符出现的频度,各个字符出现的频度 (( 次数次数 )) 是是W={15,4,4,3,2}W={15,4,4,3,2} 。。 等长编码等长编码:若采用等长办法给每个字符编码::若采用等长办法给每个字符编码:

O:000 G:001 _:010 D:011 F:100O:000 G:001 _:010 D:011 F:100则总编码长度为 则总编码长度为 (15+4+4+3+2) * 3 = 84.(15+4+4+3+2) * 3 = 84.我们考虑按各个字符我们考虑按各个字符出现的概率不同而给予不等长编码,可望减少总编码长度。各出现的概率不同而给予不等长编码,可望减少总编码长度。各字符出现概率为字符出现概率为 { 15/28,4/28,4/28,3/28,2/28 }, { 15/28,4/28,4/28,3/28,2/28 }, 取整数为取整数为 {15,{15,4,4,3,2}4,4,3,2} 如果规定,如果规定, HuffmanHuffman树的树的左子树小于右子树左子树小于右子树,则可构成右,则可构成右图所示图所示 HuffmanHuffman 树。树。 4

15

42 3G _F D

O

Page 47: 数据结构 第六章树和二叉树

6-47 中国科大《数据结构》

6.6 赫夫曼树及其应用 令左孩子分支为编码‘令左孩子分支为编码‘ 0’0’ ,右孩子分支为编码‘,右孩子分支为编码‘ 1’1’ 将根结点到叶子结点路径上的分支编码,组合起来,作为该字将根结点到叶子结点路径上的分支编码,组合起来,作为该字符的符的 HuffmanHuffman码,则可得到:字母码,则可得到:字母 O:1 _:011 G:010 D:001 O:1 _:011 G:010 D:001 F:000F:000

则总编码长度为则总编码长度为 15*1+(2+3+4+4)*3 = 54 15*1+(2+3+4+4)*3 = 54 < 84< 84 HuffmanHuffman 是一种前缀编码,解码时不会混淆是一种前缀编码,解码时不会混淆 如如 GOODGOOD 编码为:编码为: 0101100101011001

4

15

42 3

00

0 0

1

111

G _F D

O

Page 48: 数据结构 第六章树和二叉树

6-48 中国科大《数据结构》

习题 本章习题参见教师网页:http://staff.ustc.edu.cn/~leeyi