【数据结构二叉树】C非递归算法实现二叉树的先序、中序、后序遍历

引言:

遍历二叉树:指按某条搜索路径巡访二叉树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。
除了层次遍历外,二叉树有三个重要的遍历方法:先序遍历、中序遍历、后序遍历。
1、递归算法实现先序、中序、后序遍历:

(1)先序遍历:

void PreOrderTraverse(BiTree T)
{
	if(T)
	{
		cout<<T->data;
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
}

(2)中序遍历:

void InOrderTraverse(BiTree T)
{   if(T)
   {
   InOrderTraverse(T->lchild);
   cout<<T->data;
   InOrderTraverse(T->rchild);
   }
} 

(3)后序遍历

void PostOrderTraverse(BiTree T)
{   if(T)
     {  PostOrderTraverse(T->lchild); 
        PostOrderTraverse(T->rchild); 
        cout<<T->data;   
      }
} 

2.非递归算法实现先序、中序、后序遍历:

采用非递归算法则需要利用栈来实现对二叉树的遍历:
(1)先序遍历非递归算法

void  PreOrder_non_recursion(BiTree T)//先序遍历的非递归算法 
{
	LinkStack S;
	InitStack (S);   
	BiTree p,q;
	p=T;
	while(p||!StackEmpty(S))
	{
		if(p)
		{
			Push(S,*p); 
			cout<<p->data; //访问根节点 
			p=p->lchild;   //遍历左子树 
		}
		else
		{
			Pop(S,*q);
			p=q->rchild;   //遍历右子树 
		}
	}
}

(2)中序遍历非递归算法

void  InOrder_non_recursion(BiTree T)//中序遍历的非递归算法 
{
	LinkStack S;
	InitStack (S);   
	BiTree p;    
	BiTree q; 
	p=T;
	while(p||!StackEmpty(S))
	{
		if(p)
		{
			Push(S,*p); 
			p=p->lchild;   //遍历左子树 
		}
		else
		{
			Pop(S,*q);
			cout<<q->data; //访问根节点 
			p=q->rchild;   //遍历右子树 
		}
	}
}

(3)后序遍历非递归算法
(采用非递归算法实现对二叉树的后序遍历,会稍微复杂一些,本算法借用了两个栈结构)

void  PostOrder_non_recursion(BiTree T)//后序遍历的非递归算法 
{
	LinkStack l_S,r_S;
	InitStack (l_S);
	InitStack (r_S);
	BiTree p,q;    
	p=T;
	Push(l_S,*p);
	while(!StackEmpty(l_S))
	{
		Pop(l_S, *q);
		Push(r_S,*q);
		if(q->lchild){
			Push(l_S, *q->lchild);
		}
		if(q->rchild){
			Push(l_S,*q->rchild);
		}
	}
	while(!StackEmpty(r_S))
	{
		Pop(r_S,*q);
		cout<<q->data;
	}
}

3.完整代码

1、采用按照先序遍历的顺序建立二叉链表,用‘#’表示空树。如图所示:
在这里插入图片描述
2、先序遍历的递归与非递归算法的对比:

#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
using namespace std;
typedef char TElemType;
typedef int Status;

typedef struct BiTNode{  //二叉树的存储结构
    TElemType   data;	// 数据域
    struct  BiTNode *lchild; //左孩子指针
	struct  BiTNode *rchild; //右孩子指针
}BiTNode, *BiTree;


typedef struct StackNode {  //栈的存储结构
	BiTNode data;       //栈数据元素类型为树结点型 
	struct StackNode *next;
} StackNode, *LinkStack;


Status InitStack(LinkStack &S) { //栈初始化
	S = NULL;
	return OK;
}

Status Push(LinkStack &S, BiTNode e) { //入栈
	LinkStack p;
	p = new StackNode; //生成新结点
	if (!p) {return OVERFLOW;}
	p->data = e; //将新结点数据域置为e
	p->next = S; //将新结点插入栈顶
	S = p; //修改栈顶指针为p
	return OK;
}

Status Pop(LinkStack &S, BiTNode &e) {  //出栈
	LinkStack p;
	if (S == NULL)
		return ERROR; //栈空
	e = S->data; //将栈顶元素赋给e
	p = S; //用p临时保存栈顶元素空间,以备释放
	S = S->next; //修改栈顶指针
	delete p; //释放原栈顶元素的空间
	return OK;
}


bool StackEmpty(LinkStack S) {  //判断是否空栈
	if (!S)
		return true;
	return false;
}


void CreateBiTree_PreOrder(BiTree &T){ //以先序次序创建二叉树 
    char ch; 
    cin>>ch;
    if(ch=='#')
	T=NULL; 
    else{
    	T=new BiTNode;  //生成根结点
    	T->data=ch; //根结点的数据域置为ch
        CreateBiTree_PreOrder(T->lchild);//构造左子树
        CreateBiTree_PreOrder(T->rchild); //构造右子树
    }

}

void PreOrder(BiTree T){   //先序遍历的递归递归算法
	if(T)
	{
		cout<<T->data;
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}


void  PreOrder_non_recursion(BiTree T)//先序遍历的非递归算法 
{
	LinkStack S;
	InitStack (S);   
	BiTree p,q;
	p=T;
	while(p||!StackEmpty(S))
	{
		if(p)
		{
			Push(S,*p); 
			cout<<p->data; //访问根节点 
			p=p->lchild;   //遍历左子树 
		}
		else
		{
			Pop(S,*q);
			p=q->rchild;   //遍历右子树 
		}
	}
}

int main() {
	BiTree T;
	cout<<"以先序次序创建二叉链表,以#表示空子树:"<<endl;
	CreateBiTree_PreOrder(T);
	cout<<"先序序列(递归算法):"; 
	PreOrder(T); 
	cout<<"\n先序序列(非递归算法):"; 
	PreOrder_non_recursion(T);
	return 0;
}

实验结果:
在这里插入图片描述
3、中序遍历的递归与非递归算法的对比:

#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
using namespace std;
typedef char TElemType;
typedef int Status;

typedef struct BiTNode{  //二叉树的存储结构
    TElemType   data;	// 数据域
    struct  BiTNode *lchild; //左孩子指针
	struct  BiTNode *rchild; //右孩子指针
}BiTNode, *BiTree;


typedef struct StackNode {  //栈的存储结构
	BiTNode data;       //栈数据元素类型为树结点型 
	struct StackNode *next;
} StackNode, *LinkStack;


Status InitStack(LinkStack &S) { //栈初始化
	S = NULL;
	return OK;
}


Status Push(LinkStack &S, BiTNode e) { //入栈
	LinkStack p;
	p = new StackNode; //生成新结点
	if (!p) {return OVERFLOW;}
	p->data = e; //将新结点数据域置为e
	p->next = S; //将新结点插入栈顶
	S = p; //修改栈顶指针为p
	return OK;
}

Status Pop(LinkStack &S, BiTNode &e) {  //出栈
	LinkStack p;
	if (S == NULL)
		return ERROR; //栈空
	e = S->data; //将栈顶元素赋给e
	p = S; //用p临时保存栈顶元素空间,以备释放
	S = S->next; //修改栈顶指针
	delete p; //释放原栈顶元素的空间
	return OK;
}


bool StackEmpty(LinkStack S) {  //判断是否空栈
	if (!S)
		return true;
	return false;
}


void CreateBiTree_PreOrder(BiTree &T){ //以先序次序创建二叉树 
    char ch; 
    cin>>ch;
    if(ch=='#')
	T=NULL; 
    else{
    	T=new BiTNode;  //生成根结点
    	T->data=ch; //根结点的数据域置为ch
        CreateBiTree_PreOrder(T->lchild);//构造左子树
        CreateBiTree_PreOrder(T->rchild); //构造右子树
    }

}

void InOrder(BiTree T){   //中序遍历的递归递归算法
	if(T)
	{
		InOrder(T->lchild);
		cout<<T->data;
		InOrder(T->rchild);
	}
}


void  InOrder_non_recursion(BiTree T)//中序遍历的非递归算法 
{
	LinkStack S;
	InitStack (S);   
	BiTree p;    
	BiTree q; 
	p=T;
	while(p||!StackEmpty(S))
	{
		if(p)
		{
			Push(S,*p); 
			p=p->lchild;   //遍历左子树 
		}
		else
		{
			Pop(S,*q);
			cout<<q->data; //访问根节点 
			p=q->rchild;   //遍历右子树 
		}
	}
}

int main() {
	BiTree T;
	cout<<"以先序次序创建二叉链表,以#表示空子树:"<<endl;
	CreateBiTree_PreOrder(T);
	cout<<"中序序列(递归算法):"; 
	InOrder(T); 
	cout<<"\n中序序列(非递归算法):"; 
	InOrder_non_recursion(T);
	return 0;
}

实验结果:
在这里插入图片描述

4、后序遍历的递归与非递归算法的对比:

#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
using namespace std;
typedef char TElemType; 
typedef int Status;

typedef struct BiTNode{  //二叉树的存储结构
    TElemType   data;	// 数据域
    struct  BiTNode *lchild; //左孩子指针
	struct  BiTNode *rchild; //右孩子指针
}BiTNode, *BiTree;

typedef struct StackNode {  //栈的存储结构
	BiTNode data;       //栈数据元素类型为树结点型 
	struct StackNode *next;
} StackNode, *LinkStack;


Status InitStack(LinkStack &S) { //栈初始化
	S = NULL;
	return OK;
}

Status Push(LinkStack &S, BiTNode e) { //入栈
	LinkStack p;
	p = new StackNode; //生成新结点
	if (!p) {return OVERFLOW;}
	p->data = e; //将新结点数据域置为e
	p->next = S; //将新结点插入栈顶
	S = p; //修改栈顶指针为p
	return OK;
}

Status Pop(LinkStack &S, BiTNode &e) {  //出栈
	LinkStack p;
	if (S == NULL)
		return ERROR; //栈空
	e = S->data; //将栈顶元素赋给e
	p = S; //用p临时保存栈顶元素空间,以备释放
	S = S->next; //修改栈顶指针
	delete p; //释放原栈顶元素的空间
	return OK;
}

bool StackEmpty(LinkStack S) {  //判断是否空栈
	if (!S)
		return true;
	return false;
}


void CreateBiTree_PreOrder(BiTree &T){ //以先序次序创建二叉树 
    char ch; 
    cin>>ch;
    if(ch=='#')
	T=NULL; 
    else{
    	T=new BiTNode;  //生成根结点
    	T->data=ch; //根结点的数据域置为ch
        CreateBiTree_PreOrder(T->lchild);//构造左子树
        CreateBiTree_PreOrder(T->rchild); //构造右子树
    }

}

void PostOrder(BiTree T){   //后序遍历的递归递归算法
	if(T)
	{
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		cout<<T->data;
	}
}

void  PostOrder_non_recursion(BiTree T)//后序遍历的非递归算法 
{
	LinkStack l_S,r_S;
	InitStack (l_S);
	InitStack (r_S);
	BiTree p,q;    
	p=T;
	Push(l_S,*p);
	while(!StackEmpty(l_S))
	{
		Pop(l_S, *q);
		Push(r_S,*q);
		if(q->lchild){
			Push(l_S, *q->lchild);
		}
		if(q->rchild){
			Push(l_S,*q->rchild);
		}
	}
	while(!StackEmpty(r_S))
	{
		Pop(r_S,*q);
		cout<<q->data;
	}
}

int main() {
	BiTree T;
	cout<<"以先序次序创建二叉链表,以#表示空子树:"<<endl;
	CreateBiTree_PreOrder(T);
	cout<<"后序序列(递归算法):"; 
	PostOrder(T); 
	cout<<"\n后序序列(非递归算法):"; 
	PostOrder_non_recursion(T);
	return 0;
}


实验结果:
在这里插入图片描述

4.结语

对于先序、中序和后序遍历,如果采用非递归算法,则需要借助栈来实现。对于二叉树而言,还有一种大家更为熟知的遍历方式,那就是层次遍历。实现对二叉树的层次遍历,则需要借助队列来实现。实现对二叉树的层次遍历,可以参考C实现二叉树的层次遍历
欢迎大家一起来交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值