二叉树遍历(递归—非递归转换)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
B
C p 8 (7) D
E
G
F
F
返 回 目 录
C
A
A i B P->G P->D P->A 访问:C B E (9) p A C E G D F i
B
D
E
G P=NULL A B
F
P->D P->A
访问:C B E G (10)
p D i
C F G
B D E F p i P->F P->A 访问:C B E G D
22
返 回 目 录
while ((s.top>0)&& (s.tag[s.top]==1)) { t=s.data[s.top]; printf("%c ",t->data); s.top- -; } if (s.top>0) { t=s.data[s.top]; s.tag[s.top]=1; t=t->rchild; } else t=NULL; } }
T 主程序 Pre( T ) B
A
T 左是空返回 T 返回
T
B
T
C
左是空返回 右是空返回
D
T
A
printf(A); pre(T L); pre(T R);
printf(B); pre(T L); pre(T R); T C
左是空返回 T D 右是空返回 T printf(D); 返回 pre(T L); pre(T R); T 返回 T 返回
20
返 回 因此为了区分栈顶元素的右子树是否已被访问,可为其设置一 目 标志tag . 录 tag=0,表示该栈顶元素的右子树尚未访问,该栈顶元素 不能出栈,而应该进入其右子树进行访问;
tag=1,表示该栈顶元素的右子树已被访问,可将该栈顶 元素出栈,并输出其值; 显然,当一个元素刚进入栈时,其tag值应该为0,而当 进入栈顶元素的右子树访问时,应该将其tag值改为1。 (4)只有t所指向的子树访问完成且栈为空时,整个遍历过程 才能结束。 请同学们仔细分析对照后序遍历和中序遍历的区别! 二叉树后序遍历和中序遍历的主要区别在于对栈顶元素 的处理,即以上第(3)点。
18
返 回 目 录
三、二叉树后序遍历的非递归实现
过 程 演 示
tt D t t
t t
B t E F
A
C G
需保存的结点: A B’ D’ H’ K’ J L’ 输出:H K L J D
H
J
t L K
I
t=^ t=^t
t=^ t=^ t=^ t=^ 剩下的遍历过程由同学们自行完成!
19
返 回 目 录
D
方法
L
R
LDR、LRD、DLR RDL、RLD、DRL
3
返回目录
返 回 目 录
二叉树的先序遍历
D A L R
A
D B C L R D L R
D
B D L R
C
先序遍历序列:A B D C
D
4
返 回 目 录
算法实现:
递 归 算 法
先序遍历 过程演示
进入 非递归算法
5
返 回 目 录
T
void preorder(BiTree t) { if(t!=NULL) { printf("%d\t",t->data); preorder(t->lchild); preorder(t->rchild); } }
数据结构
——遍历二叉树
制作人:计科系孙玉霞
2013-6-1
数据结构——二叉树的遍历
1
返 回 目 录
6.3 遍历二叉树
遍历二叉树
二叉树的先序遍历 本 次 课 主 要 内 容
二叉树的中序遍历
二叉树的后序遍历
2
返 回 目 录
遍历二叉树
先序遍历:先访问根结点,然后分别先序遍历左子树、 右子树 中序遍历:先中序遍历左子树,然后访问根结点,最后 中序遍历右子树 后序遍历:先后序遍历左、右子树,然后访问根结点 按层次遍历:从上到下、从左到右访问各结点
14
返 回 目 录
二叉树中序遍历的非递归实现算法:
typedef struct stack{ /*栈结构定义*/ BiTree data[100]; int top;} sqstack; void push(sqstack *s,BiTree t) /*进栈*/ { s.data[s.top++]=t; } BiTree pop(sqstack *s) /*出栈*/ { if (s.top!=0) return(s.data[--s.top]); else return NULL; }
在二叉树后序遍历过程中:
(1)必须使用栈记录尚未及时得到访问的子树的根和 右子树(实际操作时只需记住子树的根即可)
(2)在遍历过程中要做的工作始终分成两部分: 当前正在访问的子树(被指针t指向) 栈中等待访问的子树
(3)当t 为空或t 所指向的子树访问完成后,若栈非空,则 考虑两种情况: 若栈顶元素的右子树尚未访问,则访问其右子树,此 时栈顶元素不能出栈; 若栈顶元素的右子树已被访问,则访问该栈顶元素, 并将其出栈;
先序序列:A 6
B D C
printf(C); pre(T L); pre(T R);
T
返回
Back
返 回 目 录
p
非递归算法
A p
B D i C F G A P->A (1) E G D i P->B P->A (2) A
B C E
F
A i B
p CFra Baidu bibliotek
B D E F
P->C P->B P->A (3)
21
返 回 目 录
二叉树后序遍历的非递归实现算法:
typedef struct stack /*栈结构定义*/ { BiTree data[100]; int tag[100]; /*为栈中每个元素设置的标记*/ int top; /*栈顶指针*/ } sqstack;
void postorder1(BiTree t) { sqstack s; s.top=0; while ((t!=NULL)||(s.top!=0)) { while (t !=NULL) { s.data[s.top]=t; s.tag[s.top]=0; s.top++; t=t->lchild; }
中序遍历: a + b * c - d - e / f
后序遍历: a b c d - * + e f / 层次遍历: 25
-+/a*efb-cd
返回目录
}
16
返 回 目 录
二叉树的后序遍历
一、二叉树后序遍历的定义:
首先按照后序遍历的顺序访问根结点的左子树; 然后按照后序遍历的顺序访问根结点的右子树。 最后访问根结点;
t
A
B D H K J L E I F C G
后序遍历的结果: HKLJDIEBFGCA
17
返 回 目 录
二、二叉树后序遍历的递归实现 void postorder(BiTree t) { if (t!=NULL) { postorder(t->lchild); postorder(t->rchild); printf("%c",t->data); } }
23
返 回 目 录
总结:
“遍历”是二叉树各种操作的基础。 由上讨论得知: 遍历二叉树是以一定规则将二叉树中的结点排列成一个线 性序列,得到二叉树中结点的先序序列或中序序列或后序
序列。
这实质上是对一个非线性结构进行线性化。
返回目录
24
返 回 目 录
练习题1:
+ a *
-
/
e
f
b
c
d
先序遍历: - + a * b - c d / e f
15
返 回 void inorder1(BiTree t) 目 { sqstack s; 录
/*非递归实现二叉树中序遍历*/
s.top=0; while((t!=NULL) || (s.top!=0)) { while (t!=NULL) { push(&s,t); t=t->lchild; } if (s.top!=0) { t=pop(&s); printf("%c ",t->data); t=t->rchild; } }
10 (15)
返 回 目 录
二叉树的中序遍历
一、二叉树中序遍历的定义:
首先按照中序遍历的顺序访问根结点的左子树; 然后访问根结点; 最后按照中序遍历的顺序访问根结点的右子树。
t A B D H J E I F C G
中序遍历的结果: HDKJLBEIA FCG
K
11
L
返 回 目 录
二、二叉树中序遍历的递归实现 #define NULL 0 Typedef struct node{ char data; struct node *lchild,*rchild; }*BiTree; Void inorder(BiTree t) { if(t!=NULL) { inorder(t–>lchild); printf(“%c”,t–>data) inorder(t–>rchild); } }
C p=NULL E (4)
D F G
i
P->B P->A
访问:C
7
G
返 回 目 录
p B C E
A
B D i C P->A 访问:C B E (6)
A p D F G i
F
G
P->D P->A
访问:C B
(5)
A
A
i B P->E P->D P->A 访问:C B p C E G D i P->D P->A 访问:C B E (8)
12
返 回 目 录
三、二叉树中序遍历的非递归实现
t t
B tt D t t t E F
A
C G
需保存的结点: A BDH L K J 输出:H DK J LB
H
J
t L K
I
t=^ t=^t
t=^ t=^ t=^ t=^
剩下的遍历过程由同学们自行完成!
13
返 回 目 录
在二叉树中序遍历过程中:
(1)必须使用栈记录尚未及时得到访问的子树的根和 右子树(实际操作时只需记住子树的根即可) (2)在遍历过程中要做的工作始终分成两部分: 当前正在访问的子树(被指针t指向) 栈中等待访问的子树 当t所指向的子树访问完成后,若栈非空,则取出栈顶元素, 访问其根结点,然后再进入其右子树访问 (3)只有t所指向的子树访问完成且栈为空时,整个遍历 过程才能结束。
C
E (11)
P->A 访问:C B E G D
9
(12)
G
返 回 目 录
C
p A B A
B D
C i F p=NULL G D
E
(13)
E P->A
F G (14)
i 访问:C B E G D F A
访问:C B E G D F
A
p=NULL
B
C D
E
G
F
i 访问:C B E G D F A
返回目录