建立一个二叉树并遍历的基本步骤
今天我们要讲的是二叉树的建立过程。这是一个很重要同时也很基础的知识,每个学数据结构的小伙伴都必备的技能。由于每个人或者不同老师所教的方法不尽相同,因此我这里使用的是我习惯的一种建立二叉树的方式,并不能代表所有的方式,但是其建立原理都是相同的。下面我们通过一个例题导入今天要讲的二叉树建立过程。
注意:本内容包含一定的递归性,与递归相关,理解内容需要对递归有认识。
例题导入
题目描述:要求建立一棵二叉树,该二叉树的每个节点只有一个数据域和两个指针域;并先序遍历输出二叉树每个节点的值。
建立规则是这样的:
从根节点开始建立,如果节点不为空,则录入该节点的数据,并继续录入左子树的数据,若子树为空,则通过录入0表示空,并继续录入右子树的数据。
样例图
输出样例
先序遍历为:
1 2 3 4 5 Press any key to continue
题目分析理解
题目分析
首先题目描述的建立过程可能不是很清楚,不过没关系,通过我们的进一步解释与下面的案例分析过程就很好理解了。
题目所描述的意思是,通过键盘录入每个节点的数据,每次录入都是从左节点开始录入的(根结点的录入可认为是第一个左节点),但是一颗二叉树节点数量一定是有限的吧,因此我们需要在没有子节点的节点下终止该结点的往后的数据录入,这里就是通过录入0来达到这种效果的。下面我们给出分析后的操作效果图。
操作分析
假设我们现在要建立如上图的这样一棵二叉树,具有四个节点,每一个节点内的数据是我们要录入的,对于每一个NULL我们录入的0,这里录入的0并不代表这个数据是0,而是通过判断来确定该结点有没有元素,0就为空,没有任何元素,也没有0。也就是说,我们需要输入9个数据(包括四个数据和5个NULL)。
过程分析
过程分析 重点!
这里假设我们要录入的数据分别是1,2,3,4因为每次都是从左子树开始录入的,所以我们的录入顺序应该是1 2 3 0 0 0 4 0 0。这个很好理解,第一个0代表3的左子树为空,因此就不会继续沿着这条路往下走了,而是转向右边,第二个0代表3的左子树也为空,因此我们沿着原路返回到2,因为2的左子树我们已经录入了,右子树现在还没有处理,因此我们现在要处理2的右子树,第三个0代表的是2的右子树也是空,于是相同的过程,我们又返回到上一级,录入右子树的值,这时右子树不为空,OK,录入右子树的数据,然后又继续往左子树开始录,第四个0代表4的左子树为空,于是转向右子树,第五个0代表4的右子树也为空,我们还是会返回到上一级,返回上一级发现,上一级的左右子树都已经满了,继续往上找,发现没有上一级了,代表现在已经回溯到根结点了,此时代表数据已经全部录入完毕。图解如下,重点是理解。
解题代码如下
//先序创建一个二叉树,并先序遍历
#include<stdio.h>
#include<stdlib.h>
typedef struct tree
{
int nValue; //数据域
struct tree *pLeft;//左指针域
struct tree *pRight;//右指针域
}Tree;
//创建二叉树 采用递归创建
void CreateTree(Tree **ptree)
{
printf("请输入节点值\n");
int num;
scanf("%d",&num);
if(num == 0)
return;
(*ptree) = (Tree*)malloc(sizeof(Tree));
(*ptree)->nValue = num;
(*ptree)->pLeft = NULL;
(*ptree)->pRight = NULL;
CreateTree(&((*ptree)->pLeft));
CreateTree(&((*ptree)->pRight));
}
//先序遍历二叉树
//Visit只是遍历过程中的一个输出函数
void Visit(Tree* root)
{
printf("%d ",root->nValue);
}
void Traversal(Tree* root)
{
if(root!=NULL)
{
Visit(root);
Traversal(root->pLeft);
Traversal(root->pRight);
}
}
int main()
{
Tree *ptree = NULL;
CreateTree(&ptree);
printf("先序遍历为:\n");
Traversal(ptree);
return 0;
}
关于二叉树的遍历,这里我们只给出先序遍历一种遍历方式,另外两种遍历方式与先序遍历几乎相同,只是输出语句的位置发生了变化,这里就不把三种方式一一给出了。感谢阅读~