第06章 树与二叉树B
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{printf(“%d”A,roo-t>data); //访问D DLR(rootB->lchild);C//递归遍历左子树
DLR(root->rchild); //递归遍历右子树
} retuDrn(0); E}
后序遍历算法 LRD (node *root) {if(root !=NULL) {LRD(root->lchild); LRD(root->rchild); printf(“%d”r,oot->data); } return(0);}
遍历目的 得到树中所有结点的一个线性排列。
遍历方法
根结点
左子树
右子树
依次遍历二叉树中的三 个组成 部分,便是遍历 了整个二叉树
假设:L:遍历左子树 v:访问根结点 R:遍
历右子树 ,则遍历整个二叉树方案共有:
vLR、LvR、LRv 、 vRL、RvL、RLv 六种。
5
若规定先左后右,则只有前三种情况:
1)建立栈stack, 初始时栈为空 2)t指向根 3)当 t不为空时,或栈stack不空时,重复:
若t不空,访问t? data后,将t入栈; t指向其左子女;
否则:栈顶元素出栈; t指向其右子女
4)结束
18
非递归的二叉树 前序遍历:
A
B
C
DE F G
H
I
J
访问A, A进栈,t指向B 栈[A] 访问B, B进栈,t指向D 栈[AB] 访问D, D进栈,t为空 栈[ABD]
17
非递归的二叉树前序遍历:
算法思路: 对于非递归算法,引入栈模拟递归过程,初始
时栈为空。 问题是如何利用栈来保存信息,使得在前序遍历节点t的左 子树后,能利用栈顶信息获取节点t的右子树的根指针? 方法是访问t? data后,将t入栈,遍历左子树;遍历完左子 树返回时,站定元素应为t,出栈,再先序遍历t的右子树。
L
V
R
A
B D
A
LV R
L VR
C
B
C
L VR
中序遍历序列:B D A C
D
9
中序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 中序遍历左子树;
(2) 访问根结点;
A
(3) 中序遍历右子树。 B
D
E L
H
J
MI
ELBAMHIDJ
10
后序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
vLR —— 先(根)序遍历, LvR —— 中(根)序遍历, LRv —— 后(根)序遍历。
根结点
左子树
右子树
6
先序遍历 (VLR)二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 访问根结点;
(2) 前序遍历左子树;
(3) 前序遍历右子树。
V
L
R
A
A
V LR
V LR
B
C
D
B
C
V LR
先序遍历序列:A B D C
(1) 后序遍历左子树;
(2) 后序遍历右子树;
L
(3) 访问根结点。
A
LR V
R
V
A L RV
B
C
B
C
D
L RV
后序遍历序列: D B C A
D
11
后序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 后序遍历左子树;
(2) 后序遍历右子树;
A
(3) 访问根结点。 B
D
E L
H
J
MI
LEBMIHJDA
a+b
+
ab
(a+b)×c ×
+
c
ab
13
分析表达式和二叉树的关系
a+b×c
(a+b)×c – d/e -
+
×
/
a×
+
cd e
b c ab
14
例:写出下图二叉树的先序、中序和后序遍历顺序。
-
+
/
遍历结果:
前序: - + a×b - c d / e f
表达式的前缀表示
a ×e
bcd
f 中序: a + b×c - d - e / f
中序遍历算法 LDR(node *root) {if(root !=NULL) {LDR(root->lchild); printf(“%d”r,oot->data); LDR(root->rchild);
} return(0);}
先序遍历算法 DLR( node *root ) {if (root !=NULL) //非空二叉树
目录
第1章 绪论 第2章 线性表 第3章 栈和队列 第4章 串 第5章 数组和广义表 第6章 树和二叉树 第7章 图 第9章 查找 第10章 排序
1
教学 内 容
1、树和森林的概念 2、二叉树的定义、性质及运算; 3、二叉树的存储结构 4、遍历二叉树 5、线索二叉树 6、树、森林、森林与二叉树的转换 7、哈夫曼树、哈夫曼编码
2
6.4 二叉树的遍历
(Binary Tree Traversal)
3
遍历概念
顺着某一条搜索路径 巡访二叉树中的结点,使 得每个结点 均被访问一次 ,而且仅被访问一次 。
“访问”的含义很广,可以是对结点作各种处 理,如:输出结点的信息、修改结点的数据值 等,但要求这种访问不破坏原来的数据结构。
4
12
分析表达式和二叉树的关系
以二叉树表示表达式的递归定义如下: 若表达式为一个数(或简单变量),则对应的二叉树中仅 有一个根结点,其数据域存放该表达式的信息; 若表达式形如“(第一操作数)(运算符)(第二操作 数)”,则对应的二叉树以左子树表示第一操作数,右子 树表示第二操作数,根Βιβλιοθήκη Baidu点的数据域存放运算符(若为一 元运算符,则左子树为空)。 操作数本身又为表达式。
D出栈,t为空 栈[AB] B出栈,t指向E 栈[A] 访问E, E进栈,t指向H 栈[AE] 访问H,H进栈,t为空 栈[AEH] H出栈,t指向J 栈[AE] 访问J, J进栈, t为空 栈[AEJ] J出栈, t为空 栈[AE] E出栈,t为空 栈[A] A出栈,t指向C 栈为空 访问C,C进栈,t指向F 栈[C] 访问F,F进栈,t为空 栈[CF] F出栈,t指向I 栈[C] 访问I, I进栈,t为空 栈[CI] I出栈,t为空 栈[C] C出栈,t指向G 栈为空 访问G,G进栈,t为空 栈[G] G出栈,t为空 栈为空
表达式的中缀表示
后序: a b c d -×+ e f / -
表达式的后缀表示
15
层次遍历(Levelorder Traversal)
从上到下,从左到右
遍历结果
- +/a* e f b -cd
16
结点数据类型自定义 typedef struct node{ int data; struct node *lchild,*rchild; } node; node *root;
D
7
7
先序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 访问根结点;
(2) 前序遍历左子树;
A
(3) 前序遍历右子树。
B
D
E L
H
J
MI
先序遍历结果:A B E L D H M I J
8
中序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 中序遍历左子树;
(2) 访问根结点; (3) 中序遍历右子树。
DLR(root->rchild); //递归遍历右子树
} retuDrn(0); E}
后序遍历算法 LRD (node *root) {if(root !=NULL) {LRD(root->lchild); LRD(root->rchild); printf(“%d”r,oot->data); } return(0);}
遍历目的 得到树中所有结点的一个线性排列。
遍历方法
根结点
左子树
右子树
依次遍历二叉树中的三 个组成 部分,便是遍历 了整个二叉树
假设:L:遍历左子树 v:访问根结点 R:遍
历右子树 ,则遍历整个二叉树方案共有:
vLR、LvR、LRv 、 vRL、RvL、RLv 六种。
5
若规定先左后右,则只有前三种情况:
1)建立栈stack, 初始时栈为空 2)t指向根 3)当 t不为空时,或栈stack不空时,重复:
若t不空,访问t? data后,将t入栈; t指向其左子女;
否则:栈顶元素出栈; t指向其右子女
4)结束
18
非递归的二叉树 前序遍历:
A
B
C
DE F G
H
I
J
访问A, A进栈,t指向B 栈[A] 访问B, B进栈,t指向D 栈[AB] 访问D, D进栈,t为空 栈[ABD]
17
非递归的二叉树前序遍历:
算法思路: 对于非递归算法,引入栈模拟递归过程,初始
时栈为空。 问题是如何利用栈来保存信息,使得在前序遍历节点t的左 子树后,能利用栈顶信息获取节点t的右子树的根指针? 方法是访问t? data后,将t入栈,遍历左子树;遍历完左子 树返回时,站定元素应为t,出栈,再先序遍历t的右子树。
L
V
R
A
B D
A
LV R
L VR
C
B
C
L VR
中序遍历序列:B D A C
D
9
中序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 中序遍历左子树;
(2) 访问根结点;
A
(3) 中序遍历右子树。 B
D
E L
H
J
MI
ELBAMHIDJ
10
后序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
vLR —— 先(根)序遍历, LvR —— 中(根)序遍历, LRv —— 后(根)序遍历。
根结点
左子树
右子树
6
先序遍历 (VLR)二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 访问根结点;
(2) 前序遍历左子树;
(3) 前序遍历右子树。
V
L
R
A
A
V LR
V LR
B
C
D
B
C
V LR
先序遍历序列:A B D C
(1) 后序遍历左子树;
(2) 后序遍历右子树;
L
(3) 访问根结点。
A
LR V
R
V
A L RV
B
C
B
C
D
L RV
后序遍历序列: D B C A
D
11
后序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 后序遍历左子树;
(2) 后序遍历右子树;
A
(3) 访问根结点。 B
D
E L
H
J
MI
LEBMIHJDA
a+b
+
ab
(a+b)×c ×
+
c
ab
13
分析表达式和二叉树的关系
a+b×c
(a+b)×c – d/e -
+
×
/
a×
+
cd e
b c ab
14
例:写出下图二叉树的先序、中序和后序遍历顺序。
-
+
/
遍历结果:
前序: - + a×b - c d / e f
表达式的前缀表示
a ×e
bcd
f 中序: a + b×c - d - e / f
中序遍历算法 LDR(node *root) {if(root !=NULL) {LDR(root->lchild); printf(“%d”r,oot->data); LDR(root->rchild);
} return(0);}
先序遍历算法 DLR( node *root ) {if (root !=NULL) //非空二叉树
目录
第1章 绪论 第2章 线性表 第3章 栈和队列 第4章 串 第5章 数组和广义表 第6章 树和二叉树 第7章 图 第9章 查找 第10章 排序
1
教学 内 容
1、树和森林的概念 2、二叉树的定义、性质及运算; 3、二叉树的存储结构 4、遍历二叉树 5、线索二叉树 6、树、森林、森林与二叉树的转换 7、哈夫曼树、哈夫曼编码
2
6.4 二叉树的遍历
(Binary Tree Traversal)
3
遍历概念
顺着某一条搜索路径 巡访二叉树中的结点,使 得每个结点 均被访问一次 ,而且仅被访问一次 。
“访问”的含义很广,可以是对结点作各种处 理,如:输出结点的信息、修改结点的数据值 等,但要求这种访问不破坏原来的数据结构。
4
12
分析表达式和二叉树的关系
以二叉树表示表达式的递归定义如下: 若表达式为一个数(或简单变量),则对应的二叉树中仅 有一个根结点,其数据域存放该表达式的信息; 若表达式形如“(第一操作数)(运算符)(第二操作 数)”,则对应的二叉树以左子树表示第一操作数,右子 树表示第二操作数,根Βιβλιοθήκη Baidu点的数据域存放运算符(若为一 元运算符,则左子树为空)。 操作数本身又为表达式。
D出栈,t为空 栈[AB] B出栈,t指向E 栈[A] 访问E, E进栈,t指向H 栈[AE] 访问H,H进栈,t为空 栈[AEH] H出栈,t指向J 栈[AE] 访问J, J进栈, t为空 栈[AEJ] J出栈, t为空 栈[AE] E出栈,t为空 栈[A] A出栈,t指向C 栈为空 访问C,C进栈,t指向F 栈[C] 访问F,F进栈,t为空 栈[CF] F出栈,t指向I 栈[C] 访问I, I进栈,t为空 栈[CI] I出栈,t为空 栈[C] C出栈,t指向G 栈为空 访问G,G进栈,t为空 栈[G] G出栈,t为空 栈为空
表达式的中缀表示
后序: a b c d -×+ e f / -
表达式的后缀表示
15
层次遍历(Levelorder Traversal)
从上到下,从左到右
遍历结果
- +/a* e f b -cd
16
结点数据类型自定义 typedef struct node{ int data; struct node *lchild,*rchild; } node; node *root;
D
7
7
先序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 访问根结点;
(2) 前序遍历左子树;
A
(3) 前序遍历右子树。
B
D
E L
H
J
MI
先序遍历结果:A B E L D H M I J
8
中序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
(1) 中序遍历左子树;
(2) 访问根结点; (3) 中序遍历右子树。