chapter 5 tree & binary tree
DESCRIPTION
Chapter 5 Tree & Binary Tree. 树的类型定义. n(n ≥ 0) 个元素的有限集合. 树的类型定义. 数据对象 D :. D 是具有相同特性的数据元素的集合。. 数据关系 R :. 若 D 为空集,则称为空树 。 否则 : (1) 在 D 中存在唯一的称为根的数据元素 root ; (2) 当 n>1 时,其余结点可分为 m (m>0) 个互 不相交的有限集 T 1 , T 2 , …, T m ,其中每一 棵子集本身又是一棵符合本定义的树, - PowerPoint PPT PresentationTRANSCRIPT
四川大学 计算机 ( 软件 ) 学院
Chapter 5
Tree & Binary Tree
四川大学 计算机 ( 软件 ) 学院
树的类型定义 n(n≥0) 个元素的有限集合
四川大学 计算机 ( 软件 ) 学院
数据对象 D :D 是具有相同特性的数据元素的集合。
若 D 为空集,则称为空树 。 否则 :
(1) 在 D 中存在唯一的称为根的数据元素 root ; (2) 当 n>1 时,其余结点可分为 m (m>0) 个互 不相交的有限集 T1, T2, …, Tm ,其中每一 棵子集本身又是一棵符合本定义的树, 称为根 root 的子树。
数据关系 R :
树的类型定义
四川大学 计算机 ( 软件 ) 学院
基本操作:
查 找 类 插 入 类
删 除 类
四川大学 计算机 ( 软件 ) 学院
Root(T) // 求树的根结点 查找类:
Value(T, cur_e) // 求当前结点的元素值 Parent(T, cur_e) // 求当前结点的双亲结点LeftChild(T, cur_e) // 求当前结点的最左孩子
RightSibling(T, cur_e) // 求当前结点的右兄弟TreeEmpty(T) // 判定树是否为空树
TreeDepth(T) // 求树的深度TraverseTree( T, Visit() ) // 遍历
四川大学 计算机 ( 软件 ) 学院
InitTree(&T) // 初始化置空树 插入类:
CreateTree(&T, definition) // 按定义构造树Assign(T, cur_e, value) // 给当前结点赋值InsertChild(&T, &p, i, c)
// 将以 c 为根的树插入为结点 p 的第 i 棵子树
四川大学 计算机 ( 软件 ) 学院
ClearTree(&T) // 将树清空
删除类:
DestroyTree(&T) // 销毁树的结构
DeleteChild(&T, &p, i)
// 删除结点 p 的第 i 棵子树
四川大学 计算机 ( 软件 ) 学院
基 本 术 语
四川大学 计算机 ( 软件 ) 学院
结点结点的度树的度叶子结点分支结点
数据元素 +若干指向子树的分支分支的个数
树中所有结点的度的最大值度为零的结点度大于零的结点 DD
HH II JJ
MM
四川大学 计算机 ( 软件 ) 学院
( 从根到结点的 )路径
孩子结点、双亲结点兄弟结点、堂兄弟结点祖先结点、子孙结点
由从根到该结点所经分支和结点构成
AA
BB CC DD
EE FF GG HH II JJ
MMKK LL
四川大学 计算机 ( 软件 ) 学院
结点的层次
树的深度
AA
BB CC DD
EE FF GG HH II JJ
MMKK LL假设根结点的层次为 1,第 l 层的结点的子树根结点的层次为 l+1
树中叶子结点所在的最大 层次
四川大学 计算机 ( 软件 ) 学院
任何一棵非空树是一个二元组 Tree = ( root , F )其中 root 被称为根结点 F 被称为子树森林
森林森林是 m ( m≥0 )棵互不相交的树的集合
AArootroot
BB CC DD
EE FF GG HH II JJ
MMKK LL
FF
四川大学 计算机 ( 软件 ) 学院
( 1 ) 有确定的根( 2 ) 树根和子树根之间为有向关系
有向树
有序树子树之间存在确定的次序关系
无序树子树之间不存在确定的次序关系
四川大学 计算机 ( 软件 ) 学院
对比树型结构和线性结构的结构特点
四川大学 计算机 ( 软件 ) 学院
线性结构 树型结构第一个数据元素 ( 无前驱 )
根结点 ( 无前驱 )
最后一个数据元素 ( 无后继 )
多个叶子结点 ( 无后继 )
其它数据元素(一个前驱、 一个后继 )
其它数据元素(一个前驱、 多个后继 )
四川大学 计算机 ( 软件 ) 学院
二叉树的类型定义
四川大学 计算机 ( 软件 ) 学院
二叉树或为空树,或是由一个根结点加上两棵分别称为左子树和右子树的、互不交叉的二叉树组成
A
B
C
D
E
F
G
H K
根结点
左子树
右子树
四川大学 计算机 ( 软件 ) 学院
二叉树的五种基本形态
N
空树空树 只含根结点只含根结点
N NN
L RR
右子树为空树右子树为空树
L
左子树为空树左子树为空树
左右子树均不为空树
左右子树均不为空树
四川大学 计算机 ( 软件 ) 学院
二叉树的主要基本操作
查 找 类插 入 类
删 除 类
四川大学 计算机 ( 软件 ) 学院
Root(T) Value(T, e) Parent(T, e)
LeftChild(T, e) RightChild(T, e)
LeftSibling(T, e) RightSibling(T, e)
BiTreeEmpty(T) BiTreeDepth(T)
四川大学 计算机 ( 软件 ) 学院
PreOrderTraverse(T, Visit())
InOrderTraverse(T, Visit())
PostOrderTraverse(T, Visit())
LevelOrderTraverse(T, Visit())
四川大学 计算机 ( 软件 ) 学院
InitBiTree(&T)
Assign(T, &e, value)
CreateBiTree(&T, definition)
InsertChild(T, p, LR, c)
四川大学 计算机 ( 软件 ) 学院
ClearBiTree(&T)
DestroyBiTree(&T)
DeleteChild(T, p, LR)
四川大学 计算机 ( 软件 ) 学院
二叉树的重要特性
四川大学 计算机 ( 软件 ) 学院
• 性质 1 :• 在二叉树的第 i 层上至多有 2i-1 个结点。 (i≥1)
用归纳法证明:
归纳基:
归纳假设: 归纳证明:
i = 1 层时,只有一个根结点: 2i-1 = 20 = 1 ;假设对所有的 j , 1≤ j i ,命题成立;二叉树上每个结点至多有两棵子树,则第 i 层的结点数 ≤ 2i-2 2 = 2i-1 。
四川大学 计算机 ( 软件 ) 学院
• 性质 2 : 深度为 k 的二叉树上至多含 2k-1 个结点( k≥1 )。
证明: 基于上一条性质,深度为 k 的二叉树上的结点数至多为 20+21+ +2k-1 = 2k-1 。
四川大学 计算机 ( 软件 ) 学院
• 性质 3 : 对任何一棵二叉树,若它含有 n0 个叶子结点、 n2 个度为 2 的结点,则必存在关系式: n0 = n2+1 。
证明:设 二叉树上结点总数 n = n0 + n1 + n2
又 二叉树上分支总数 b = n1+2n2
而 b = n-1 = n0 + n
1 + n2 - 1
由此, n0 = n2 + 1 。
四川大学 计算机 ( 软件 ) 学院
两类特殊的二叉树:满二叉树:指的是深度为 k 且含有 2k-1
个结点的二叉树。
完全二叉树:树中所含的 n 个结点和满二叉树中编号为 1 至 n 的结点一一对应。
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
a
b c
d e f g
h i j
四川大学 计算机 ( 软件 ) 学院
• 性质 4 : 具有 n 个结点的完全二叉树的深度为 log2n +1 。
证明:设完全二叉树的深度为 k
则根据第二条性质得 2k-1≤ n < 2k
即 k-1 ≤ log2 n < k
因为 k 只能是整数,因此, k =log2n + 1 。
四川大学 计算机 ( 软件 ) 学院
• 性质 5 :
若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点:(1) 若 i=1 ,则该结点是二叉树的根,无双亲,否则,编号为 i/2 的结点为其双亲结点;
(2) 若 2i>n ,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;(3) 若 2i+1>n ,则该结点无右孩子结点, 否则,编号为 2i+1 的结点为其右孩子结点。
四川大学 计算机 ( 软件 ) 学院
二叉树的存储结构
二、二叉树的链 式存储表示
一、二叉树的顺 序存储表示
四川大学 计算机 ( 软件 ) 学院
完全二叉树的 一般二叉树的 数组表示 数组表示
顺序存储表示顺序存储表示
四川大学 计算机 ( 软件 ) 学院
A
B
C
D
E
F
A B D C E F 0 1 2 3 4 5 6 7 8 9 10 11 12 13
1
4
0
13
2
6
四川大学 计算机 ( 软件 ) 学院
单支树
由于一般二叉由于一般二叉树必须仿照完树必须仿照完全二叉树那样全二叉树那样存储,可能会存储,可能会浪费很多存储浪费很多存储空间,单支树空间,单支树就是一个极端就是一个极端情况情况
四川大学 计算机 ( 软件 ) 学院
A
D
E
B
C
F
rootlchild data rchild
结点结构二叉链表
四川大学 计算机 ( 软件 ) 学院
链表表示链表表示
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
A
D
E
B
C
F
root
三叉链表parent lchild data rchild
结点结构
四川大学 计算机 ( 软件 ) 学院
二叉链表的静态结构
四川大学 计算机 ( 软件 ) 学院
二叉树遍历二叉树遍历(Binary Tree Traversal)(Binary Tree Traversal)
四川大学 计算机 ( 软件 ) 学院
顺着某一条搜索路径巡访二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次
问题的提出
“ 访问”的含义可以很广,如:输出结点的信息等
四川大学 计算机 ( 软件 ) 学院
“遍历”是任何类型均有的操作,对线性结构而言,只有一条搜索路径 (因为每个结点均只有一个后继 ),故不需要另加讨论。而二叉树是非线性结构,每个结点有两个后继,则存在如何遍历即按什么样的搜索路径遍历的问题
四川大学 计算机 ( 软件 ) 学院
对“二叉树”而言,可以有三条搜索路径
1 .先上后下的按层次遍历2 .先左(子树)后右(子树)的遍历3 .先右(子树)后左(子树)的遍历
四川大学 计算机 ( 软件 ) 学院
设 访问根结点 记作 V 遍历根的左子树 记作 L 遍历根的右子树 记作 R 则可能的遍历次序有
前序 前序 VLR VLR 逆前序 逆前序 VRLVRL
中序 中序 LVR LVR 逆中序 逆中序 RVLRVL
后序 后序 LRV LRV 逆后序 逆后序 RLVRLV
层次遍历层次遍历
四川大学 计算机 ( 软件 ) 学院
前序遍历 前序遍历 (Preorder Traversal)(Preorder Traversal)• 若二叉树为空,则空操作若二叉树为空,则空操作• 否则否则
–访问根结点访问根结点 (V)(V)–前序遍历左子树前序遍历左子树 (L)(L)–前序遍历右子树前序遍历右子树 (R)(R)
遍历结果遍历结果 - +- + aa ** bb - - c dc d / / e fe f
四川大学 计算机 ( 软件 ) 学院
•若二叉树为空,则空操作若二叉树为空,则空操作•否则否则–中序遍历左子树中序遍历左子树 (L)(L)
–访问根结点访问根结点 (V)(V)
–中序遍历右子树中序遍历右子树 (R)(R)
遍历结果遍历结果 aa ++ bb ** cc -- dd -- ee / / ff
中序遍历 中序遍历 (Inorder Traversal)(Inorder Traversal)
表达式语法树表达式语法树
四川大学 计算机 ( 软件 ) 学院
后序遍历 后序遍历 (Postorder Traversal)(Postorder Traversal)•若二叉树为空,则空操作若二叉树为空,则空操作•否则否则
–后序遍历左子树后序遍历左子树 (L)(L)
–后序遍历右子树后序遍历右子树 (R)(R)
–访问根结点访问根结点 (V)(V)
遍历结果遍历结果 a b c da b c d - * +- * + e fe f // --
四川大学 计算机 ( 软件 ) 学院
层次遍历层次遍历 (Levelorder Traversal)(Levelorder Traversal)
从上到下,从左到右从上到下,从左到右
遍历结果遍历结果 - - +/+/ aa** e fe f b b --cdcd
四川大学 计算机 ( 软件 ) 学院
按给定的表达式建相应二叉树由前缀表达式建树例如 : -×+abc/de
由中缀表达式建树 例如: (a+b)×c–d/e
由后缀表达式建树例如: ab+c×de/-
四川大学 计算机 ( 软件 ) 学院
对应前缀表达式 -×+abc/de
的二叉树
a b
c d e
-
×
+
/
特点:
操作数为叶子结点 运算符为分支结点
四川大学 计算机 ( 软件 ) 学院
对应中缀表达式 (a+b)×c-d/e 的二叉树
a b
c d e
-
×
+
/
特点:
操作数为叶子结点 运算符为分支结点
四川大学 计算机 ( 软件 ) 学院
对应后缀表达式 ab+c×de/- 的二叉树
a b
c d e
-
×
+
/
特点:
操作数为叶子结点 运算符为分支结点
四川大学 计算机 ( 软件 ) 学院
a+b
(a+b)×c – d/ea+b×c
分析表达式和二叉树的关系
a b
+
a
b c
×
+
a b
c×
+(a+b)×c
a b
c d e
-
×
+/
四川大学 计算机 ( 软件 ) 学院
由遍历序历生成二叉树由遍历序历生成二叉树 由二叉树的 由二叉树的前序前序序列和序列和中序中序序列序列可可以以唯一地确定一棵二叉树唯一地确定一棵二叉树 由二叉树的 由二叉树的后序后序序列和序列和中序中序序列序列可可以以唯一地确定一棵二叉树唯一地确定一棵二叉树 由二叉树的 由二叉树的前序前序序列和序列和后序后序序列序列不不可可唯一地确定一棵二叉树唯一地确定一棵二叉树
四川大学 计算机 ( 软件 ) 学院
仅知二叉树的先序序列“ abcdefg” 不能唯一确定一棵二叉树,
由二叉树的先序和中序序列建树
如果同时已知二叉树的中序序列“ cbdaegf” ,则会如何? 二叉树的先序序列
二叉树的中序序列左子树
左子树 右子树
右子树
根
根
四川大学 计算机 ( 软件 ) 学院
a b c d e f gc b d a e g fa
ab b
cc
dd
ee
ffg
g
a
b
c d
e
f
g
^ ^ ^ ^
^
^ ^
^
先序序列
中序序列
四川大学 计算机 ( 软件 ) 学院
前序序列前序序列 {ABHFDECKG}{ABHFDECKG}
中序序列中序序列 {HBDFAEKCG} {HBDFAEKCG}
四川大学 计算机 ( 软件 ) 学院
问题是有 问题是有 nn 个数据值,可能构个数据值,可能构造造多少种不同多少种不同的二叉树?的二叉树? 我们可以固定前序排列,选择 我们可以固定前序排列,选择所所有可能有可能的中序排列的中序排列
二叉树的计数二叉树的计数
四川大学 计算机 ( 软件 ) 学院
二叉树的计数二叉树的计数有有 00 个个 , 1, 1 个个 , 2, 2 个个 , 3, 3 个结点的不同二叉树如下个结点的不同二叉树如下
四川大学 计算机 ( 软件 ) 学院
具有具有 44 个结点的不同二叉树个结点的不同二叉树!!
)!2(
1
1
1
12 nn
n
nnb C
n
nn
计算具有计算具有 nn 个结点的不同二叉树的棵数个结点的不同二叉树的棵数CatalanCatalan 函数函数
四川大学 计算机 ( 软件 ) 学院
树的存储结构一、双亲表示法二、孩子表示法三、孩子兄弟表示法
四川大学 计算机 ( 软件 ) 学院
A
B C D
E F
G
0 A -11 B 02 C 03 D 04 E 2 5 F 26 G 5
data parent双亲表示法
四川大学 计算机 ( 软件 ) 学院
A
B C D
E F
G
0 A -11 B 02 C 03 D 04 E 25 F 26 G 5
data firstchild 1 2 3
4 5
6
孩子链表表示法-1000224
四川大学 计算机 ( 软件 ) 学院
A
B C D
E F
G
AB C E D F G
root
AB C E D F G
孩子兄弟表示法
四川大学 计算机 ( 软件 ) 学院
孩子兄弟表示法孩子兄弟表示法 data firstChild nextSibling
四川大学 计算机 ( 软件 ) 学院
• 6.4 树和森林– 树的存储结构
• 双亲表示法– 实现:定义结构数组存放树的结点,每个结点含两个域:
» 数据域:存放结点本身信息» 双亲域:指示本结点的双亲结点在数组中位置
– 特点:找双亲容易,找孩子难
typedef struct node{ datatype data; int parent;}JD;
JD t[M];
四川大学 计算机 ( 软件 ) 学院
a
b c
d e f
hg i
a
c
d
e
f
g
h
i
b
0
1
2
2
3
5
5
5
1
0 9
6
0
1
2
3
4
5
7
8
9
data parent
0 号单元不用或存结点个数
如何找孩子结点
四川大学 计算机 ( 软件 ) 学院
• 孩子表示法– 多重链表:每个结点有多个指针域,分别指向其子树的根
» 结点同构:结点的指针个数相等,为树的度 D» 结点不同构:结点指针个数不等,为该结点的度 d
data child1 child2 ………. childD
data degree child1 child2 ………. childd
– 孩子链表:每个结点的孩子结点用单链表存储,再用含 n 个元素的结构数组指向每个孩子链表
孩子结点: typedef struct node { int child; // 该结点在表头数组中下标 struct node *next; // 指向下一孩子结点 }JD;表头结点: typedef struct tnode { datatype data; // 数据域 struct node *fc; // 指向第一个孩子结点 }TD; TD t[M]; //t[0] 不用
空环域个数为 n(k-1)+1, 其中 k为树的度。
四川大学 计算机 ( 软件 ) 学院
a
b c
d e f
hg i
6
0
1
2
3
4
5
7
8
9
a
c
d
e
f
g
h
i
b
data fc
2 3 ^
4 5 ^
^
9 7 8 ^
6 ^
^
^
^
^如何找双亲结点
四川大学 计算机 ( 软件 ) 学院
– 带双亲的孩子链表
6
1
2
3
4
5
7
8
9
a
c
d
e
f
g
h
i
b
data fc 2 3
4 5
9 7 8
6
^
^
^
^
^
^
^
^
^
0
1
2
2
3
5
5
5
1
parenta
b c
d e f
hg i
四川大学 计算机 ( 软件 ) 学院
• 孩子兄弟表示法(二叉树表示法)– 实现:用二叉链表作树的存储结构,链表中每个结点的两个
指针域分别指向其第一个孩子结点和下一个兄弟结点– 特点
» 操作容易» 破坏了树的层次
typedef struct node{ datatype data; struct node *fch, *nsib;}JD;
a
b c
d e f
hg i
a
b c
d e f
g h i
^
^
^
^ ^ ^
^ ^ ^ ^
四川大学 计算机 ( 软件 ) 学院
森林与二叉树森林与二叉树
的转换的转换
四川大学 计算机 ( 软件 ) 学院
B C D
E F G
H
I J K
1 .森林中第一棵树的根结点
2 .森林中第一棵树的子树森林
3 .森林中其它树构成的森林
森林由三部分构成
四川大学 计算机 ( 软件 ) 学院
森林转化成二叉树森林转化成二叉树
的规则的规则
四川大学 计算机 ( 软件 ) 学院
若若 FF 为空,即为空,即 nn = 0 = 0 ,则,则 对应的二叉树对应的二叉树 BB 为空二叉树为空二叉树 若若 FF 不空,则不空,则 对应二叉树对应二叉树 BB 的根的根 rootroot((BB)) 是是 FF 中第中第 一棵树一棵树 TT11 的根的根 rootroot((TT11)) ,其左子树,其左子树为为 BB((TT1111, , TT1212, …, , …, TT11mm)) ,其中,,其中, TT1111, , TT1212,,
……,, TT11mm 是是 rootroot((TT11)) 的子树;其右子的子树;其右子 树为树为 BB((TT22, , TT33, …, , …, TTnn)) ,其中,,其中, TT22, , TT33, ,
… …, , TTnn 是除是除 TT11 外其它树构成的森林外其它树构成的森林
四川大学 计算机 ( 软件 ) 学院
二叉树转换为森林二叉树转换为森林
的规则的规则
四川大学 计算机 ( 软件 ) 学院
如果如果 BB 为空,则对应的森林为空,则对应的森林 FF也为也为空空 如果如果 BB 非空,则非空,则 FF 中第一棵树中第一棵树 TT11 的根为的根为 rootroot ;; TT11 的的根根 的子树森林的子树森林 ((TT1111, , TT1212, …, , …, TT11m m )) 是由是由 rootroot 的左子树的左子树 LBLB转换而来,转换而来, FF 除了除了TT11
之外其余的树组成的森林之外其余的树组成的森林 ((TT22, , TT33, …,, …,
TTn n )) 是由是由 rootroot 的右子树的右子树 RBRB 转换而成转换而成的的 森林森林
四川大学 计算机 ( 软件 ) 学院
森林与二叉树的转换森林与二叉树的转换
四川大学 计算机 ( 软件 ) 学院
树 的 遍 历树 的 遍 历深度优先遍历深度优先遍历
树的先根次序遍历树的先根次序遍历树的后根次序遍历树的后根次序遍历
广度优先遍历广度优先遍历树的层次次序遍历树的层次次序遍历
四川大学 计算机 ( 软件 ) 学院
森林的先根遍历森林的先根遍历若森林若森林 FF 为空为空 , , 返回返回否则否则 :: 访问访问 FF 的第一棵树的根结点的第一棵树的根结点 先根次序遍历第一棵树的子先根次序遍历第一棵树的子树森林树森林 先根次序遍历其它树组成的先根次序遍历其它树组成的森林森林
四川大学 计算机 ( 软件 ) 学院
森林的后根遍历森林的后根遍历若森林若森林 FF 为空,返回为空,返回否则否则 :: 后根次序遍历第一棵树的后根次序遍历第一棵树的子树森林子树森林 后根次序遍历其它树组成后根次序遍历其它树组成的森林的森林 访问访问 FF 的第一棵树的根结的第一棵树的根结点点
四川大学 计算机 ( 软件 ) 学院
森林的层次遍历森林的层次遍历若森林若森林 FF 为空,返回为空,返回否则否则 :: 依次遍历各棵树的根结点依次遍历各棵树的根结点 依次遍历各棵树根结点的依次遍历各棵树根结点的所有子女所有子女 依次遍历这些子女结点的依次遍历这些子女结点的子女结点子女结点
四川大学 计算机 ( 软件 ) 学院
A
B C D
E F G
H
I J K
先根遍历A B E F C D G H I J K
后根遍历E F B C I J K H G D A
层次遍历:A B C D E F G H I J K
四川大学 计算机 ( 软件 ) 学院
二叉树的类定义二叉树的类定义
四川大学 计算机 ( 软件 ) 学院
template <class Type>class BinTreeNode {private: BinTreeNode<Type> *LChild,*RChild; Type data; };template <class Type> class BinaryTree {private: BinTreeNode<Type> *root; };
四川大学 计算机 ( 软件 ) 学院
二叉树前序遍历递归算法二叉树前序遍历递归算法template <class Type>void BinaryTree<Type>:: PreOrder(BinTreeNode<Type>*current){ if ( current != NULL ) { cout << current→data; PreOrder ( current→LChild ); PreOrder ( current→RChild ); }}
四川大学 计算机 ( 软件 ) 学院
二叉树中序遍历递归算法二叉树中序遍历递归算法template <class Type>void BinaryTree <Type>:: InOrder(BinTreeNode<Type>*current) { if ( current != NULL ) { InOrder ( current→LChild ); cout << current→data; InOrder ( current→RChild ); }}
四川大学 计算机 ( 软件 ) 学院
二叉树后序遍历递归算法template <class Type> void BinaryTree<Type>:: PostOrder(BinTreeNode<Type>*current) { if ( current != NULL ) { PostOrder ( current→LChild ); PostOrder ( current→RChild ); cout << current→data; }}
四川大学 计算机 ( 软件 ) 学院
二叉树前序遍历二叉树前序遍历非递归算法非递归算法
四川大学 计算机 ( 软件 ) 学院
template <class Type>void BinaryTree<Type>:: PreOrder(BinTreeNode<Type> *p ){ do { while ( p != NULL ) { cout << p->data; Push ( s, p ); p = p->LChild; } if ( !Empty ( s ) ) { p = pop ( s ); p = p->RChild; } }while ( ( !Empty ( s ) ) || ( p != NULL ) )
}
四川大学 计算机 ( 软件 ) 学院
二叉树中序遍历二叉树中序遍历非递归算法非递归算法
四川大学 计算机 ( 软件 ) 学院
template <class Type>void BinaryTree<Type>:: PreOrder(BinTreeNode<Type> *p ){ do { while ( p != NULL ) { Push ( s, p ); p = p->LChild; } if ( !Empty ( s ) ) { p = pop ( s ); cout << p->data; p = p->RChild; } }while ( ( !Empty ( s ) ) || ( p != NULL ) )
}
四川大学 计算机 ( 软件 ) 学院
应用二叉树遍历的事例应用二叉树遍历的事例
四川大学 计算机 ( 软件 ) 学院
利用二叉树遍历计算二叉树结点个数template <class Type> void BinaryTree<Type>:: Size( BinTreeNode<Type> *current ){ if ( current != NULL ) return Size ( current→LChild )+ Size ( current→RChild )+1; else return 0;}
四川大学 计算机 ( 软件 ) 学院
计算二叉树的高度template <class Type> int BinaryTree<Type>:: Depth ( BinTreeNode <Type> *t ){ if ( t == NULL ) return 0; else return 1+ Max( Depth( t→LChild ), Depth( t→RChild ) );}
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
四川大学 计算机 ( 软件 ) 学院
线索二叉树
四川大学 计算机 ( 软件 ) 学院
遍历二叉树的结果是, 求得结点的一个线性序列
A
B
C
D
E
F
G
H K
先序序列 A B C D E F G H K中序序列 B D C A H G K F E后序序列 D C B H K G F E A
四川大学 计算机 ( 软件 ) 学院
指向该线性序列中的“前驱”和 “后继” 的指针,称作“线索”
与其相应的二叉树,称作 “线索二叉树”
包含 “线索” 的存储结构,称作 “线索链表”
A B C D E F G H K
^ D ^
C ^
^ B
E ^
四川大学 计算机 ( 软件 ) 学院
对线索链表中结点的约定在二叉链表的结点中增加两个标志域LTag 和 RTag,并作如下规定 :若该结点的左子树不空,则 LChild域的指针指向其左孩子, 且左标志 LTag 的值为 0
否则, LChild域的指针指向其“前驱”, 且左标志 LTag 的值为 1
四川大学 计算机 ( 软件 ) 学院
若该结点的右子树不空,则 RChild域的指针指向其右孩子, 且右标志 RTag 的值为 0
否则, RChild域的指针指向其“后继”, 且右标志 RTag 的值为 1
如此定义的二叉树的存储结构称作“线索链表”
四川大学 计算机 ( 软件 ) 学院
LTag LTag = 0, = 0, LChildLChild 为为指针指针 ,, 指向指向左孩子左孩子LTagLTag = 1, = 1, LChildLChild 为为线索线索 ,, 指向指向前驱前驱RTagRTag = 0, = 0, RChildRChild 为为指针指针 ,, 指向指向右孩子右孩子RTagRTag = 1, = 1, RChildRChild 为为线索线索 ,, 指向指向后继后继
四川大学 计算机 ( 软件 ) 学院
猜一猜 ,是哪一种线索二叉树
四川大学 计算机 ( 软件 ) 学院
后序序列后序序列 D B E C AD B E C A
前序序列前序序列 A B D C EA B D C E
四川大学 计算机 ( 软件 ) 学院
带表头结点的中序线索二叉树
四川大学 计算机 ( 软件 ) 学院
寻找当前结点寻找当前结点在中序下的后继在中序下的后继
四川大学 计算机 ( 软件 ) 学院
if (pRTag==1) if (pRChild!=T.root) 后继为 pRChild else 无后继else //pRTag==0 if (pRChild!=T.root) 后继为当前结点右 子树的中序下的第 一个结点 else 出错情况
A
B
D E
C
F
H I
K
G
J
L
四川大学 计算机 ( 软件 ) 学院
寻找当前结点寻找当前结点在中序下的前趋在中序下的前趋
四川大学 计算机 ( 软件 ) 学院
if (pLTag==1) if (pLChild!=T.root) 前驱为 pLChild else 无前驱else //pLTag==0 if (pLChild!=T.root) 前驱为当前结点左 子树的中序下的最 后一个结点 else 出错情况
A
B
DE
C
F
H I
K
G
J
L
四川大学 计算机 ( 软件 ) 学院
哈 夫 曼 树 (Huffman Tree)(Huffman Tree)
与哈 夫 曼 编 码
四川大学 计算机 ( 软件 ) 学院
结点的路径长度 从根结点到该结点的路径上分 支的数目
结点间路径长度结点间路径长度 ((Path LengthPath Length)) 连接两结点的路径上的分支数连接两结点的路径上的分支数
四川大学 计算机 ( 软件 ) 学院
树的树的带权路径长度带权路径长度((Weighted Path Length,WPLWeighted Path Length,WPL)) 树的各叶结点所带的权值与该树的各叶结点所带的权值与该 结点到根的路径长度的乘积的 结点到根的路径长度的乘积的 和和
树的路径长度 树中每个结点的路径长度之和
1
0
n
iii lwWPL
四川大学 计算机 ( 软件 ) 学院
在所有含 n个叶子结点、并带相同权值的 m叉树中,必存在一棵其带权路径长度取最小值的树,称为“最优树” ,
或“哈夫曼树” (Huffman Tree)(Huffman Tree)
四川大学 计算机 ( 软件 ) 学院
具有不同带权路径长度的二叉树
哈哈夫曼树中,权值大的结点离根最近夫曼树中,权值大的结点离根最近
四川大学 计算机 ( 软件 ) 学院
227 9 7 9
77 55
44
99
22
WPL(T)=
72+52+23+43+92
=60
WPL(T)=
74+94+53
+42+21
=89
55
44
四川大学 计算机 ( 软件 ) 学院
构造哈夫曼树构造哈夫曼树(( 以二叉树为例以二叉树为例 ))
四川大学 计算机 ( 软件 ) 学院
根据给定的 n 个权值 {w1, w2,
…,
wn} ,造 n 棵二叉树的集合
F = {T1, T2, … , Tn} ,
其中每棵二叉树中均只含一个带权 值为 wi 的根结点,其左、右子
树为 空树;
(1)(1)
四川大学 计算机 ( 软件 ) 学院
在 F 中选取其根结点的权值为最 小的两棵二叉树,分别作为左、 右子树构造一棵新的二叉树,并 置这棵新的二叉树根结点的权值 为其左、右子树根结点的权值之 和;
(2)(2)
四川大学 计算机 ( 软件 ) 学院
从 F 中删去这两棵树,同时加入 刚生成的新树
重复 (2)(2) 和 (3)(3) 两步,直至 F 中只 含一棵树为止
(3)(3)
(4)(4)
四川大学 计算机 ( 软件 ) 学院
99已知权值 已知权值 W={ 5, 6, 2, 9, 7 }W={ 5, 6, 2, 9, 7 }
55 66 22 77
55 22
7766 99 77
66 77
131399
55 22
77
四川大学 计算机 ( 软件 ) 学院
66 77
131399
55 22
77
99
55 22
77
1616
66 77
1313
29290
0 0
0
1
1 1
10000 0101 1010
110110 111111
四川大学 计算机 ( 软件 ) 学院
任何一个字符的编码都不是同一任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀字符集中另一个字符的编码的前缀
前缀编码前缀编码
利用哈夫曼树可以构造一种利用哈夫曼树可以构造一种不等长的二进制编码,并且构造所得不等长的二进制编码,并且构造所得的的哈夫曼编码哈夫曼编码是一种是一种最优前缀编码最优前缀编码,,即使所传即使所传电文的总长度最短电文的总长度最短
四川大学 计算机 ( 软件 ) 学院
设给出一段报文 设给出一段报文 CAST CAST SAT AT A TASACAST CAST SAT AT A TASA
字符集合是 字符集合是 { C, A, S, T }{ C, A, S, T } ,,各个字符出现的频度各个字符出现的频度 (( 次数次数 )) 是 是 WW== { { 2, 7, 4, 5 }2, 7, 4, 5 } 若给每个字符以等长编码若给每个字符以等长编码
AA : 00 T : 10 C : 01 S : 11 : 00 T : 10 C : 01 S : 11则总编码长度为 则总编码长度为 ( 2+7+4+5 ) * 2 = 36( 2+7+4+5 ) * 2 = 36
四川大学 计算机 ( 软件 ) 学院
以各字符出现概率以各字符出现概率 {2,7,4,5}{2,7,4,5} 为各叶结为各叶结点权值,建立哈夫曼树,得哈夫曼编码点权值,建立哈夫曼树,得哈夫曼编码(( 不等长编码不等长编码 )) AA:0 T:10 C:110 :0 T:10 C:110 S:111S:111总编码长度为总编码长度为7*1+5*2+(2+4)*3=357*1+5*2+(2+4)*3=35总编码长度正好等总编码长度正好等于哈夫曼树的带于哈夫曼树的带权路径长度权路径长度 WPLWPL
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法const unsigned int n=256; // 字符数const unsigned int m=256*2-1; // 结点总数
struct HTNode{ // 压缩用 Huffman 树结点 unsigned long weight; // 字符频度(权值) unsigned int parent,lchild,rchild;};
struct Buffer{ // 字节缓冲压缩用 Huffman 树 char ch; // 字节 unsigned int bits; // 实际比特数 };
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法 (class HuffmanTree(1))class HuffmanTree{ //Huffman 树 public: void Code(); // 编码 void UnCode(); // 译码private: HTNode HT[m+1]; // 树结点表 (HT[1] 到 HT[m]) char Leaf[n+1]; // 叶结点对应字符 (leaf[1] 到 leaf[n]) // 叶结点对应编码 (*HuffmanCode[1] 到 *HuffmanCode[n]) char *HuffmanCode[n+1]; unsigned int count; // 频度大于零的字符数 // 字符对应在树结点表的下标 (char_index[0] 到 char_index[n-1]) unsigned int char_index[n]; unsigned long size; // 被压缩文件长度 FILE *infp,*outfp; // 输入 / 出文件 Buffer buf; // 字符缓冲
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法 (class HuffmanTree(2)) void Stat();// 统计字符出现频度并过滤掉频度为零的字符 // 在 HT[0]~HT[k] 中选择 parent 为 -1 ,树值最小的两个结点 s1,s2 void Select(unsigned int k, unsigned int &s1, unsigned int &s2); void Write(unsigned int bit); // 向 outfh 中写入一个比特 void Write(unsigned int num,unsigned int k);// 向 outfh 中写入 k 个比特 void WriteToOutfp(); // 强行写入 outfh void Read(unsigned int &bit); // 从 infh 中读出一个比特 void Read(unsigned int &num,unsigned int k);// 从 infh 中读出 k 个比特 //0~num-1 之间的整数用二进位表示所需的位数 int NToBits(unsigned int num); // 由编码文件中存储的树结构建立 Huffman 树 unsigned int CharToInt(char ch); // 将字符转化为整型数 void CreateFromCodeFile(); // 由被压缩文件建立 Huffman 树 , 将树结构存入编码文件的文件头部 // 中 , 并求每个字符的 Huffman 编码 void CreateFromSourceFile();};
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法 (CreateFromSourceFile()(1))void HuffmanTree::CreateFromSourceFile()// 由被压缩文件建立 Huffman 树 , 将树结构存入编码文件的文件头部中// 并求每个字符的 Huffman 编码{ Stat();// 统计字符出现频度并过滤掉频度为零的字符
// 由被压缩文件建立 Huffman 树 unsigned int i,s1,s2; for(i=1;i<=n;i++)HT[i].parent=HT[i].lchild=HT[i].rchild=0; for(i=count+1;i<=2*count-1;i++){// 建立 Huffman 树 Select(i-1,s1,s2); // 选择 parent 为 0 ,权值最小的两个结点 s1,s2 HT[s1].parent=HT[s2].parent=i; HT[i].parent=0;HT[i].lchild=s1;HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; }
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法 (CreateFromSourceFile()(2)) // 将树结构存入编码文件的文件头部中 unsigned int l; buf.bits=0; // 清空缓冲区 buf.ch=0; rewind(outfp); fwrite(&size,sizeof(unsigned int),1,outfp); Write(count-1,8); for(i=1;i<=count;i++) fwrite(&Leaf[i],sizeof(char),1,outfp); l=NToBits(2*count-1); for(i=count+1;i<=2*count-1;i++){ Write(HT[i].lchild,l); Write(HT[i].rchild,l); }
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法 (CreateFromSourceFile()(3)) // 求每个字符的 Huffman 编码 unsigned int start,c,f,tem; char *cd; // 编码临时变量 for(i=1;i<=n;i++) if(HuffmanCode[i]!=NULL){ delete []HuffmanCode[i]; // 释放存储空间 HuffmanCode[i]=NULL; } cd=new char[count]; // 分配求编码的工作空间 cd[count-1]='\0'; // 编码结束符 for(i=1;i<=count;i++){ // 逐位求 Huffman 编码 start=count-1; // 编码结束符位置 for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[c].parent) // 从叶到根求编码 if(HT[f].lchild==c)cd[--start]='0'; else cd[--start]='1'; HuffmanCode[i]=new char[count-start]; // 为第 i 个字符编码分配空间 strcpy(HuffmanCode[i],&cd[start]); // 从 cd 复制编码到 HuffmanCode } delete []cd;}
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法void HuffmanTree::Code(){ // 求字符的编码 // 增加打开输入 / 出文件 char ch; unsigned int i,c; for(i=0;i<=n;i++)HuffmanCode[i]=NULL; CreateFromSourceFile(); rewind(infp); ch=fgetc(infp); while(feof(infp)==0){ c=char_index[CharToInt(ch)]; for(i=0;i<strlen(HuffmanCode[c]);i++){ if(HuffmanCode[c][i]=='0')Write(0); else Write(1); } ch=fgetc(infp); } WriteToOutfp(); fclose(infp);fclose(outfp);}
四川大学 计算机 ( 软件 ) 学院
哈夫曼算法void HuffmanTree::UnCode(){ // 译码 , // 增加打开输入 / 出文 unsigned int bit,c,i; CreateFromCodeFile(); // 建立 Huffman 树 Read(bit); for(i=0;i<size;i++){ c=2*count-1; //2*count-1 为根结点的下标 while((HT[c].lchild!=0||HT[c].rchild!=0)&&feof(infp)==0){ if(bit==0)c=HT[c].lchild; else c=HT[c].rchild; Read(bit); } fputc(Leaf[c],outfp); // 将字符写入 outfp 中 } fclose(infp);fclose(outfp);}
四川大学 计算机 ( 软件 ) 学院
哈夫曼树推广( m叉哈夫曼树)定理
对于度数只为 m或 0的正则 m叉树,叶结点个数 n0与度为 m的结点数 nm这间存在关系 :
n0=(m-1)*nm+1构造构造 mm 叉哈夫曼树的方法叉哈夫曼树的方法
如如 n0=(m-1)*nm+1 成立,则仿照一般的二叉哈夫曼树进行构造(只每次选出 m棵根结点权值最小的 m叉树合并为一棵新的 m叉树)如 n0=(m-1)*nm+1 不成立,则可添加若干个权为 0的叶结点使其成立,然后再仿照一般的二叉哈夫曼树进行构造 (在画 m叉树时权为 0的结点可不画出 )