数据结构6.2——树的遍历(递归/非递归)

本文详细介绍了树的遍历方法,包括前序、后序和层次遍历,以及递归和非递归的实现策略。通过递归函数展示了如何使用栈和队列来执行这些操作,以理解如何在数据结构中遍历树形结构。
摘要由CSDN通过智能技术生成

一、树的遍历

        遍历一棵树实际上就是把树的结点排成一个线性序列的过程。

        按照跟的访问位置不同,将树的遍历分为前序遍历和后序遍历。

        又由于树有层次性,还可以用层次遍历一棵树。 

前序遍历:

先访问根结点,再从左到右按照前序遍历的方式访问根结点的每一棵子树。

后序遍历:

先从左到右按照后序遍历的方式访问根结点的每一棵子树,再访问根结点。

层次遍历:

从左到右依次访问每层的结点。

二、递归-遍历

        因为前后序、层次遍历本身具有递归性,因此采用递归方式实现前后序、层次遍历更简单。 

  • 递归前序遍历

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###
  • 非递归后序遍历 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值