遍历二叉树的操作定义、遍历算法实现、层次遍历

树在计算机领域应用广泛,尤以二叉树最为常用。如在操作系统中,用树来表示文件目录的组织结构,在编译系统中,用树来表示源程序的语法结构,在数据库系统中,数结构也是信息的重要组织形式之一。本文仅是本人学习二叉树遍历的学习记录,希望以此对树结构有深刻的理解。

注:四、五两部分用到的栈和队列的操作请看:

循环队列的基本操作

顺序栈的相关操作

遍历二叉树分三种:先序遍历二叉树(根左右)、中序遍历二叉树(左根右)、后序遍历二叉树(左右根)。

一、三种遍历方式的操作定义

1、先序遍历二叉树的操作定义:
若二叉树为空,则空操作;否则
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树;在这里插入图片描述

2、中序遍历二叉树操作定义:
若二叉树为空,则空操作;否则
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
在这里插入图片描述
3、后序遍历二叉树操作定义:
若二叉树为空,则空操作;否则
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
在这里插入图片描述
用二叉树表示算术表达式:
在这里插入图片描述
先序序列:-+ab-cd/ef(前缀表示(波兰式))
中序遍历:a+b
c-d-e/f(中缀表示)
后序遍历:abcd-*+ef/-(后缀表示(逆波兰式))

前缀表达式就是先进行符号运算,也叫波兰表示
中缀表达式就是我们平时所用的标准四则运算表达式
后缀表达式是一种不需要括号的后缀表达法,也称为逆波兰表示
利用二叉树可以将中缀表示转化为后缀表示。

二、根据遍历序列确定二叉树

  • 若二叉树中各结点的值均不相同,则二叉树结点的先序序列、中序序列和后序序列都是唯一的
  • 有二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一 一颗二叉树
    在这里插入图片描述后序遍历,根结点必在后序序列尾部,所以先找到根:A,然后判断哪些在左子树上,哪些在右子树上,然后找到左子树的根:B,以此类推找根结点
    在这里插入图片描述

但根据先序序列和后序序列无法确定二叉树

三、遍历的算法实现

1)先序遍历(根左右)

扫描二维码关注公众号,回复: 8842874 查看本文章
Status PreOrderTraverse(BiTree T){
if(T==NULL)
	return OK;//空二叉树
else{
	visit(T);//访问根结点,例如输出根节点cout<<T->data;
	PreOrderTraverse(T->lchild);//递归遍历左子树
	PreOrderTraverse(T->rchild);//递归遍历右子树

执行过程:设主程序为Pre(T)

void Pre(BiTree *T){
if(T!=NULL){
	printf("%d\t",T->data);
	pre(T->lchild);
	pre(T->rchild);
	}
}	

2)中序遍历(左根右)

void InOrderTraverse(BiTree T)
{
	if(T)	//二叉树非空
	{
		InOrderTraverse(T->lchild);//递归遍历左子树
		visit(T);//访问根结点,或写做cout<<T->data;
		InOrderTraverse(T->rchild);//递归遍历右子树
	}
}

3)后序遍历(左右根)

Status PostOrderTraverse(BITree T)
{
	if(T){
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		cout<<T->data;
	}
}

从虚线的出发点到终点的路径上,每个结点经过3次。
第一次经过时访问=先序遍历
第二次经过时访问=中序遍历
第三次经过时访问=后序遍历
时间复杂度O(n)//每个结点只访问一次
空间复杂度S(n)//栈占用的最大辅助空间。

四、中序遍历非递归算法(用栈实现)

二叉树中序遍历的非递归算法的关键:在中序遍历过某结点的整个左子树后,如何找到该结点根以及右子树。
基本思想:
(1)建立一个栈
(2)根结点进栈,遍历左子树,为空则根结点出栈。
(3)根结点出栈,输出根结点,遍历右子树。

Status InOrderTraverse(BiTree T)
{
	BiTree p;
	InitStack(S);
	p=T;
	while(p||!StackEmpty(S))
	{
	if(p)
	{
		Push(S,p);
		p=p->lchild;
	}
	else
	{
		Pop(S,q);
		cout<<q->data;
		p=p->rchild;
		
	}
	return OK;
  }
}

五、二叉树的层次遍历(队列实现)

对于一棵二叉树,从根结点开始,按从上到下、从左到右的顺序访问每一个结点,每个结点仅访问一次。

算法设计思路:使用一个队列
1、将根结点进队;
2、队不空时循环:从队列中出队一个结点*p,访问它;

  • 若它有左孩子结点,将左孩子结点进队
  • 若它有右孩子结点,将右孩子结点进队

也就是出队一个元素后,将它的左右孩子入队。

使用队列类型定义如下:

typedef struct{
	BTNode data[MaxSize];//存放队中元素
	int front,rear;   //队头和队尾指针
	}SqQueue;  //顺序循环队列类型 

二叉树层次遍历算法

void LevelOrder(BTNode *b)
{
	BTNode *p;
	SqQueue *qu;
	InitQueue(qu);	//初始化队列
	enQueue(qu,b);	//根结点指针进入队列
	while(!QueueEmpty(qu))	//队不为空,则循环
	{
		deQueue(qu,p);	//出对结点p
		cout<<p->data;	//访问结点p
		if(p->lchild!=NULL)
			enQueue(qu,p->lchild);//有左孩子时将其进队
		if(p->rchild!=NULL)
			enQueue(qu,p->rchild);//有右孩子时将其进队
				
	}
}
//所有元素出队后,程序结束

内容参考:《数据结构》严蔚敏

发布了34 篇原创文章 · 获赞 85 · 访问量 4612

猜你喜欢

转载自blog.csdn.net/weixin_45895026/article/details/104047357