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

引言:

遍历二叉树 :指按某条搜索路径巡访二叉树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。

除了层次遍历外,二叉树有三个重要的遍历方法:先序遍历、中序遍历、后序遍历。
1、递归算法实现先序、中序、后序遍历:

(1)先序遍历:

cpp 复制代码
void PreOrderTraverse(BiTree T)
{
	if(T)
	{
		cout<<T->data;
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
}

(2)中序遍历:

cpp 复制代码
void InOrderTraverse(BiTree T)
{   if(T)
   {
   InOrderTraverse(T->lchild);
   cout<<T->data;
   InOrderTraverse(T->rchild);
   }
} 

(3)后序遍历

cpp 复制代码
void PostOrderTraverse(BiTree T)
{   if(T)
     {  PostOrderTraverse(T->lchild); 
        PostOrderTraverse(T->rchild); 
        cout<<T->data;   
      }
} 

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

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

c 复制代码
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)中序遍历非递归算法

c 复制代码
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)后序遍历非递归算法

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

c 复制代码
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、先序遍历的递归与非递归算法的对比:

c 复制代码
#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、中序遍历的递归与非递归算法的对比:

c 复制代码
#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、后序遍历的递归与非递归算法的对比:

c 复制代码
#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;
}

实验结果:

欢迎大家一起来交流~

相关推荐
CHANG_THE_WORLD3 分钟前
C++ 文件读取函数完全指南
开发语言·c++
阿正的梦工坊7 分钟前
JavaScript 闭包 × C++ 类比:彻底搞懂闭包
开发语言·javascript·c++
6Hzlia8 分钟前
【Hot 100 刷题计划】 LeetCode 72. 编辑距离 | C++ 经典 DP 增删改状态转移
c++·算法·leetcode
穿条秋裤到处跑8 分钟前
每日一道leetcode(2026.04.16):距离最小相等元素查询
算法·leetcode·职场和发展
赵优秀一一12 分钟前
SQLAlchemy学习记录
开发语言·数据库·python
无限进步_19 分钟前
【C++】寻找字符串中第一个只出现一次的字符
开发语言·c++·ide·windows·git·github·visual studio
孬甭_30 分钟前
字符函数及字符串函数
c语言·开发语言
摇滚侠38 分钟前
Java 进阶教程,全面剖析 Java 多线程编程
java·开发语言
KevinCyao44 分钟前
php彩信接口代码示例:PHP使用cURL调用彩信网关发送图文消息
android·开发语言·php
装疯迷窍_A1 小时前
以举证方位线生成工具为例,分享如何在Arcgis中创建Python工具箱(含源码)
开发语言·python·arcgis·变更调查·举证照片