一、树的遍历
遍历一棵树实际上就是把树的结点排成一个线性序列的过程。
按照跟的访问位置不同,将树的遍历分为前序遍历和后序遍历。
又由于树有层次性,还可以用层次遍历一棵树。
前序遍历:
先访问根结点,再从左到右按照前序遍历的方式访问根结点的每一棵子树。
后序遍历:
先从左到右按照后序遍历的方式访问根结点的每一棵子树,再访问根结点。
层次遍历:
从左到右依次访问每层的结点。
二、递归-遍历
因为前后序、层次遍历本身具有递归性,因此采用递归方式实现前后序、层次遍历更简单。
-
递归前序遍历
void preorder (tree p)
{
int i;
if(p!=NULL){
printf("%c",p->data);//先输出根结点的值
for(i=0;i<m;i++){//再前序遍历
preorder(p->child[i]);//从左到右
}
}
}
-
递归后序遍历
void preorder (tree p)
{
int i;
if(p!=NULL){
for(i=0;i<m;i++){//先后序遍历,找到第一个最左的、没有孩子的结点(从左到右)
preorder(p->child[i]);
}
printf("%c",p->data);//再输出根结点的值
}
}
-
递归层次遍历
分析:
先从第一层开始,访问根节点;
再进入第二层,从左到右依次访问,此时第二层的所有结点为第一层根结点的孩子;
再进入下一层,从左到右依次访问,此时第三层的所有结点为第二层结点的孩子;
......
因此,在进入下一层时,要先将上一层的所有结点保存(从左到右保存),下一层所有结点刚好是上一层结点的孩子。
显然,因为队列先进先出的特点,保存的容器(数据结构)选择队列,队列中的每个元素均为等待被访问的结点。
void levelorder (tree t)
{
tree queue[100];//队列指针
tree p;
int f,r;
f=0;r=1;//队列首和尾(用队列时的必备——首和尾,要满足循环条件)
quenu[0]=t;
while(f<r){//队列不为空
p=quenu[f];
printf("%c",p->data);//访问队头结点
f++;//队头结点后退一个
for(i=0;i<m;i++){
if(p->child[i]){
queue[r]=p->child[i];//孩子结点入队
r++;
}
}
}
}
🐖: 大家也可以试一试用循环队列处理~
三、非递归-遍历
-
非递归前序遍历
分析:
根据栈后进先出的特点, 将每个结点的孩子从右往左依次进栈,注意:第一个孩子不进栈;
根结点为空:不必输出这个空结点,根结点指向栈顶结点(此时栈顶结点是该空结点的双亲的右边一个兄弟)/ (若双亲没兄弟了,就会是双亲的双亲的兄弟)(一直到所有结点均被访问过了才结束)
根结点不为空:要输出这个非空跟结点,要先将其除了第一个孩子外从右往左进栈(如果孩子存在),再将根结点转变为第一个孩子(从左到右)
(完整代码:)
#include <stdio.h>
#include <stdlib.h>
#define max 3
typedef char datatype;
typedef struct node
{
datatype data;
struct node *child[max];
}node,*tree;
//建立一棵树,返回根节点
tree createtree()
{
char x;
int i;
tree t;
if((x=getchar())=='#') t=NULL;
else{
t=(tree)malloc(sizeof(node));
t->data=x;
for(i=0;i<max;i++){
t->child[i]=createtree();
}
}
return t;
}
void preorder(tree root)
{
tree stack[100];//创建栈
int i;
int top=-1;
while (root||top!=-1)
{
if (root)//根结点不为空时,输出并让其孩子入栈,转变根结点为第一个孩子
{
printf("%c",root->data);//输出根结点
for (i=m-1;i>0;i--)//所有非空孩子结点入栈
if (root->child[i]!=NULL)
{
top++;
stack[top]=root->child[i];
}
root=root->child[0];//根结点转变
}
else//根结点为空时,栈顶元素出栈
{
root=stack[top--];//栈顶结点出栈
}
}
}
int main ()
{
tree root;
printf("please input the sequence of the tree:\n");
root=createtree();
printf("非递归前序序列:\n");
preorder (root);
return 0;
}
//测试案例:AB###CE###FH###I####G###D###
-
非递归后序遍历