问题的提出
在二叉树的一些应用的,常常要求在树中查找具有某种特征的结点,或者对树中的所有结点进行逐一处理。这就提出了一个遍历二叉树的问题,就是如何按某条搜索路径访问树中的每个结点,使得每个结点都被访问到且仅被访问一次。
对于二叉树的遍历,定义了三种不同的方法:先序遍历,中序遍历,后序遍历。别分表示:先访问根结点,再访问左结点,最后访问右结点。同理,中序即左根右,后序即为左右根。还有一种遍历路径层次遍历,顾名思义就是按照每一层的元素对二叉树进行遍历。
如上图,先序遍历为ABCDEFGHK;中序遍历为BDCAEHGKF;后序遍历为DCBHKGFEA;而按层次遍历为ABECFDGHK;
遍历算法描述(先序遍历建立二叉树并输出)
由于是按先序遍历,所以建立二叉树时,遍历访问时,用户输入时都应该按照先序遍历的顺序进行。同时为了避免二义性,用户输入时必须将叶子结点的左右孩子指针用空格输入,表示这个结点为空。遍历结点时,要对每个结点进行操作,将这些操作提出来单独写成visit()函数。
#include<stdio.h>
typedef struct BiTNode {
char data;
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode, *BiTree;
//创建一棵二叉树 用户按照先序遍历的路径输入数据
//为了避免二义性,所以用户输入时对于叶子结点的左右孩子要以空格的形式输入
void CreateBiTree(BiTree &T)
{
char c;
scanf("%c", &c);
if (c == ' ')
{ //如果是第一次输入,输入空格则表示这是一个空树,如果是后面递归调用时输入的空格,则说明T->l(r)child是NULL
T = NULL;
}
else //输入的是具体数值,则开辟新结点将数据输入进入data域,并且对其左右孩子指针进行递归操作
{
T = new BiTNode;
T->data = c;
CreateBiTree(T->lchild); //按照先序遍历的路径进行建立,所以这三行的顺序是固定的
CreateBiTree(T->rchild); //同时用户必须按照先序遍历的顺序进行输入
}
}
//遍历二叉树时对其每个结点要进行各种操作,而这些操作都可应单独写出来,放到visit函数中
void visit(char c,int lever)
{
printf("%c 位于第 %d 层\n", c, lever);
}
//前序遍历二叉树
void Preoder(BiTree T, int lever)
{
if (T) //通过判断结点是否为空来决定是否继续进行操作
{
visit(T->data, lever);
Preoder(T->lchild, lever + 1);
Preoder(T->rchild, lever + 1);
}
}
void main()
{
int lever = 1;
BiTree T = NULL;
CreateBiTree(T);
Preoder(T, lever);
}
本笔记所依据的教材为严薇敏版的《数据结构及应用算法教程》
部分图片来源于华中师范大学云课堂
所有代码在Visual Studio 2017上均可正常运行
如有错误欢迎指出