1、二叉树的深度遍历
二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树的所有结点,使得每个结点被访问一次且仅被访问一次。
对于二叉树的深度遍历,有前序遍历二叉树、中序遍历二叉树、后序遍历二叉树三种形式,下面分别进行学习和介绍。
1.1 二叉树的前序遍历
1)前序递归遍历
规则是若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。如下图所示,遍历的顺序为ABDGHCEIF。
前序递归遍历的代码实现,如下所示。
1
2
3
4
5
6
7
8
9
10
|
//前序递归遍历 void PreOrderTraverse(BiTree t)
{ if (t != NULL)
{
printf ( "%c " , t->data);
PreOrderTraverse(t->lchild);
PreOrderTraverse(t->rchild);
}
} |
2)前序非递归遍历
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同的规则访问它的左子树;当访问其左子树时,再访问它的右子树,因此其处理过程如下:
对于任一结点p:
a. 访问结点p,并将结点p入栈;
b. 判断结点p的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点p,循环置a;若不为空,则将p的左孩子置为当前结点p;
c. 直到p为空,并且栈为空,则遍历结束。
前序非递归遍历代码实现,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//前序非递归遍历 int NoPreOrderTraverse(BiTree t)
{ SqStack s;
InitStack(&s);
BiTree tmp = t;
if (tmp == NULL)
{
fprintf (stdout, "the tree is null.\n" );
return ERROR;
}
while ((tmp != NULL) || (IsEmpty(&s) != 1))
{
while (tmp != NULL)
{
Push(&s, tmp);
printf ( "%c " , tmp->data);
tmp = tmp->lchild;
}
if (IsEmpty(&s) != 1)
{
Pop(&s, &tmp);
tmp = tmp->rchild;
}
}
return OK;
} |
1.2 中序遍历二叉树
1)中序递归遍历
规则是若树为空,则空操作返回,否则从根结点开始(注意这里并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。如下图所示,遍历的顺序为:GDHBAEICF。
中序递归遍历代码实现如下所示。
1
2
3
4
5
6
7
8
9
10
|
//中序递归遍历 void InOrderTraverse(BiTree t)
{ if (t != NULL)
{
InOrderTraverse(t->lchild);
printf ( "%c " , t->data);
InOrderTraverse(t->rchild);
}
} |
2)中序非递归遍历
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一个根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才停止访问,然后按相同的规则访问其右子树。其处理过程如下:
对于任一结点:
a. 若其左孩子不为空,则将p入栈,并将p的左孩子设置为当前的p,然后对当前结点再进行相同的操作;
b. 若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的p置为栈顶结点的右孩子;
c. 直到p为空并且栈为空,则遍历结束。
中序非递归遍历代码实现如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//中序非递归遍历二叉树 int NoInOrderTraverse(BiTree t)
{ SqStack s;
InitStack(&s);
BiTree tmp = t;
if (tmp == NULL)
{
fprintf (stderr, "the tree is null.\n" );
return ERROR;
}
while (tmp != NULL || (IsEmpty(&s) != 1))
{
while (tmp != NULL)
{
Push(&s, tmp);
tmp = tmp->lchild;
}
if (IsEmpty(&s) != 1)
{
Pop(&s, &tmp);
printf ( "%c " , tmp->data);
tmp = tmp->rchild;
}
}
return OK;
} |
1.3 后序遍历二叉树
1)后序递归遍历
规则是若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。遍历的顺序为:GHDBIEFCA。
后序递归遍历代码实现,如下所示。
1
2
3
4
5
6
7
8
9
10
|
//后序递归遍历 void PostOrderTraverse(BiTree t)
{ if (t != NULL)
{
PostOrderTraverse(t->lchild);
PostOrderTraverse(t->rchild);
printf ( "%c " , t->data);
}
} |
2)后序非递归遍历
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问,并且左孩子在右孩子之前访问才能访问根结点,这就为流程控制带来了难题。下面介绍一种思路。
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点p,先将其入栈。若p不存在左孩子和右孩子,则可以直接访问它,或者p存在左孩子或右孩子,但是其左孩子和右孩子都已经被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将p的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子之前别访问,左孩子和右孩子都在根结点前面被访问。
后序非递归遍历代码实现,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
//后序非递归遍历二叉树 int NoPostOrderTraverse(BiTree t)
{ SqStack s;
InitStack(&s);
BiTree cur; //当前结点
BiTree pre = NULL; //前一次访问的结点
BiTree tmp;
if (t == NULL)
{
fprintf (stderr, "the tree is null.\n" );
return ERROR;
}
Push(&s, t);
while (IsEmpty(&s) != 1)
{
GetTop(&s, &cur); //
if ((cur->lchild == NULL && cur->rchild == NULL) || (pre != NULL && (pre == cur->lchild || pre == cur->rchild)))
{
printf ( "%c " , cur->data); //如果当前结点没有孩子结点或者孩子结点都已被访问过
Pop(&s, &tmp);
pre = cur;
}
else
{
if (cur->rchild != NULL)
{
Push(&s, cur->rchild);
}
if (cur->lchild != NULL)
{
Push(&s, cur->lchild);
}
}
}
return OK;
} |
2、二叉树的广度遍历
广度遍历二叉树(即层次遍历)是用队列来实现的,从二叉树的第一层(根结点)开始,自上而下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。如下图所示,遍历的顺序为:ABCDEFGHI。
按照从根结点到叶结点、从左子树到右子树的次序访问二叉树的结点,具体思路如下:
A. 初始化一个队列,并把根结点入队列;
B. 当队列为非空时,循环执行步骤3到步骤5,否则执行步骤6;
C. 出队列取得一个结点,访问该结点;
D. 若该结点的左子树为非空,则将该结点的左子树入队列;
E. 若该结点的右子树为非空,则将该结点的右子树入队列;
F. 结束。
广度遍历二叉树代码实现,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//层次遍历二叉树 - 广度遍历二叉树 - 队列 int TraverseBiTree(BiTree t)
{ LinkQueue q;
InitQueue(&q);
BiTree tmp = t;
if (tmp == NULL)
{
fprintf (stderr, "the tree is null.\n" );
return ERROR;
}
InsertQueue(&q, tmp);
while (QueueIsEmpty(&q) != OK)
{
DeQueue(&q, &tmp);
printf ( "%c " , tmp->data);
if (tmp->lchild != NULL)
{
InsertQueue(&q, tmp->lchild);
}
if (tmp->rchild != NULL)
{
InsertQueue(&q, tmp->rchild);
}
}
return OK;
} |
3、二叉树的建立
如果要在内存中建立一个如下左图这样的树,wield能让每个结点确认是否有左右孩子,我们对它进行扩展,变成如下右图的样子,也就是将二叉树中的每个结点的空指针引出一个虚结点,其值为一个特定值,比如”#”,称之为扩展二叉树。扩展二叉树就可以做到一个遍历序列确定一棵二叉树了。如前序遍历序列为AB#D##C##。
有了这样的准备,就可以看看如何生成一棵二叉树了。假设二叉树的结点均为一个字符,把刚才前序遍历序列AB#D##C##用键盘挨个输入,实现的算法如下所示。
二叉树建立实现代码一,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//创建树 //按先后次序输入二叉树中结点的值(一个字符),#表示空树 //构造二叉链表表示的二叉树 BiTree CreateTree(BiTree t) { char ch;
scanf ( "%c" , &ch);
if (ch == '#' )
{
t = NULL;
}
else
{
t = (BitNode *) malloc ( sizeof (BitNode));
if (t == NULL)
{
fprintf (stderr, "malloc() error in CreateTree.\n" );
return ;
}
t->data = ch; //生成根结点
t->lchild = CreateTree(t->lchild); //构造左子树
t->rchild = CreateTree(t->rchild); //构造右子树
}
return t;
} |
二叉树建立实现代码二,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//创建树方法二 int CreateTree2(BiTree *t)
{ char ch;
scanf ( "%c" , &ch);
if (ch == '#' )
{
(*t) = NULL;
}
else
{
(*t) = (BiTree) malloc ( sizeof (BitNode));
if ((*t) == NULL)
{
fprintf (stderr, "malloc() error in CreateTree2.\n" );
return ERROR;
}
(*t)->data = ch;
CreateTree2(&((*t)->lchild));
CreateTree2(&((*t)->rchild));
}
return OK;
} |
其实建立二叉树,也是利用了递归的原理。只不过在原来应该打印结点的地方,改成生成结点、给结点赋值的操作而已。因此,完全可以用中序或后序遍历的方式实现二叉树的建立,只不过代码里生成结点和构造左右子树的代码顺序交互一下即可。
4、二叉树的深度
树中结点的最大层次称为树的深度。对于二叉树,求解树的深度用以下两种方法实现。即非递归和递归的方法实现。
递归求解二叉树的深度实现代码,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//二叉树的深度 - 递归 //返回值: 二叉树的深度 int BiTreeDeep(BiTree t)
{ int dept = 0;
if (t)
{
int lchilddept = BiTreeDeep(t->lchild);
int rchilddept = BiTreeDeep(t->rchild);
dept = lchilddept >= rchilddept ? (lchilddept + 1) : (rchilddept + 1);
}
return dept;
} |
对于非递归求解二叉树的深度,这里采用了层次遍历的原理,通过层次遍历,找到二叉树的最后一个结点。然后,根据该结点,寻找其双亲结点,即找到其上一层,此时深度dept加1,依次进行,直到根结点为止。
非递归求解二叉树深度的实现,如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
//返回二叉树的深度 - 非递归 - 受层次遍历二叉树的影响 //返回值: 二叉树的深度 int NoBiTreeDeep(BiTree t)
{ LinkQueue q;
InitQueue(&q);
BiTree tmp = t;
if (tmp == NULL)
{
return ERROR;
}
InsertQueue(&q, tmp);
while (QueueIsEmpty(&q) != OK)
{
DeQueue(&q, &tmp);
//printf("%c ", tmp->data);
if (tmp->lchild != NULL)
{
InsertQueue(&q, tmp->lchild);
}
if (tmp->rchild != NULL)
{
InsertQueue(&q, tmp->rchild);
}
}
int deep = 0;
BiTree m = tmp;
BiTree n = t;
while (m != n)
{
InsertQueue(&q, n);
while (QueueIsEmpty(&q) != OK)
{
DeQueue(&q, &tmp);
if (m == tmp->lchild || m == tmp->rchild)
{
deep++;
m = tmp;
break ;
}
if (tmp->lchild != NULL)
{
InsertQueue(&q, tmp->lchild);
}
if (tmp->rchild != NULL)
{
InsertQueue(&q, tmp->rchild);
}
}
}
return deep + 1; //深度从1开始
|
相关推荐
数据结构二叉树的源代码包含二叉树的基本操作: 各种遍历,深度计算
数据结构课程设计--二叉树遍历及其应用、对树的先序遍历、后序遍历、中序遍历、层序遍历、二叉树的深度及其叶子树、并打印树形。
(选做)【基本要求】从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立)【测试数据】如输入:ABC##DE#G##F###(其中#表示空格字符)则输出结果为 先序:ABCDEGF中序:CBEGDFA后序:...
数据结构二叉树的遍历 二叉树的深度 二叉树的某结点层次 二叉树结点数
前序遍历 中序遍历 后序遍历 深度遍历 广度遍历 插入排序 选择排序 冒泡排序 快速排序 堆排序 希尔排序 合并排序 快速3排序
包含了二叉树的建立与遍历,遍历包含前序,中序(两种),后序遍历,以及二叉树的深度计算。程序健壮性较强。
数据结构二叉树遍历求树叶数及树的深度,个人作业,仅供大家参考或改进
数据结构 上机实验2,包括深度,层次遍历二叉树,计算深度等,c++描述的源代码
实现了二叉树的前中后遍历,以及层次遍历,求出了二叉树的深度,叶子个数。 实验报告还包含目录,所有遍历方法的解释,以及结果展示和结论改进
树型结构是一类重要的非线性数据结构,而二叉树是最为重要,最为常用的类型。树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可以用树来形象表示。树在计算机领域中也得到广泛应用,如在编译程序...
按先序扩展序列建立二叉树,先序、中序、后序遍历的递归算法,二叉树遍历的非递归算法,层次的非递归算法,求二叉树的深度。
该程序为数据结构中基本的二叉树创建与遍历,按照先序遍历输入数据,并可获得二叉树的深度和叶子个数。本程序已使用VS2008调试成功。
数据结构二叉树,先序,中序,后序遍历,深度,广度优先搜索,所有的功能一应俱全,大家可以自行组装,别忘了,评分哦
数据结构对二叉树结构的C++代码实现,包含基本的建立二叉树,各种方式遍历二叉树,深度计算、结点个数计算等等
(1)以二叉链表作为存储结构,从键盘以先序次序输入各个结点(空格字符表示空树)建立一棵二叉树; (2)对(1)中生成的二叉树进行判空; (3)对(1)中生成的二叉树进行遍历(分别实现先序遍历、中序遍历、后序...
9、 按先序遍历的扩展序列建立二叉树的存储结构 10、二叉树先序、中序、后序遍历的递归算法 11、二叉树中序遍历的非递归算法 12、二叉树层次遍历的非递归算法 13、求二叉树的深度(后序遍历) 14、建立树的存储结构
C语言的, 数据结构的作业 求二叉树的深度(后序遍历)
前序中序等遍历二叉树的算法源代码, 广度优先:首先访问初始点vi,并将其标记为已访问,接着访问vi的所有未被访问的邻接点vi1到vit;并都记为已访问过,然后按照vi1到vit的顺序,访问一个接点的所有未被访问的邻...
数据结构C语言版二叉树多种遍历算法(前序、中序、后序并且分别有递归和非递归两种,层次遍历)实现.
4、实现输出以上二叉树先序、中序和后序遍历序列中第k个数据元素的操作; 5、判断二叉树是否是完全二叉树; //先序遍历递归算法 public void preRootTraverse(BiTreeNode T){ if(T != null){ System.out.print(T...