【二叉树】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;
}

实验结果:

欢迎大家一起来交流~

相关推荐
晨曦_子画3 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
Black_Friend12 分钟前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
软工菜鸡24 分钟前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert
南宫生26 分钟前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY36 分钟前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
残月只会敲键盘36 分钟前
php代码审计--常见函数整理
开发语言·php
xianwu54336 分钟前
反向代理模块
linux·开发语言·网络·git
午言若37 分钟前
C语言比较两个字符串是否相同
c语言
ktkiko1142 分钟前
Java中的远程方法调用——RPC详解
java·开发语言·rpc
AI视觉网奇1 小时前
sklearn 安装使用笔记
人工智能·算法·sklearn