中序遍历二叉树的非递归实现(利用栈)

本文详细介绍了二叉树中序遍历的递归与非递归实现方法。递归实现简洁明了,遵循左根右原则。非递归实现采用栈结构辅助,通过不断出栈进栈模拟中序遍历特性,实现左根右的遍历顺序。文章提供了完整的代码示例,包括栈结构、二叉树节点结构及其操作函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

中序遍历二叉树的非递归实现
  • 之前的博客写了递归的实现,说白了也就是不断自己调用自身,保持左根右的顺序。只需写出整体逻辑结构,程序会自己递归复杂的过程,大体即为:
void inTraverseByRecur(Tree& T)
{
	if(T)
	{	
		inTraverseByRecur(T->lchild);
		cout<<T->data;
		inTraverseByRecur(T->rchild);
	}
}
  • 而非递归实现我采用了栈结构作辅助,因为中序遍历其为左根右,它本身遍历的特性可用不断的出栈进栈模拟。当我们以T为树的根结点时,要想做到中序遍历,需要以下几步:
    ①.若根结点T存在,将T压入栈中,若T->lchild为真(即T有左孩子),更新它的左孩子为根结点:即T=T->lchild,重复步骤①,直到一直往左走找不到左孩子为止(此时找到了中序序列的首结点),转至步骤②。
    ②.因为当前结点无左孩子,按照中序遍历左根右,则该结点出栈。若该结点有右孩子,则将右孩子视为根结点,转至步骤①,直到走到中序序列尽头,栈为空为止。

  • 以下为完整代码,包含了栈结构,二叉树结点结构及它们的操作函数,递归及非递归的实现函数我都放在了里面。

  • 这里有一些细节需要注意,传递指针和传递引用的区别,栈中的数据域元素存储的类型为结点结构。

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始化容量 
#define STACK_INC_SIZE 10	  //栈的分配增量 

typedef char ElementType;  //二叉树的数据域元素类型 

/*二叉树结点结构*/ 
typedef struct BiTree{
	struct BiTree* lchild;
	struct BiTree* rchild;
	ElementType data;
}TreeNode,*Tree;

typedef Tree elemType;	   //栈存储的数据元素类型为二叉树结点结构 

/*栈的数据结构*/ 
typedef struct{
	elemType* base;  //栈底指针 
	elemType* top;	 //栈顶指针 
	int stackSize;   //当前已分配的栈总存储空间 
}SqStack; 

void initStack(SqStack& S);  		   	  //构造空栈并初始化 
void pushStack(SqStack& S,elemType data); //数据元素进栈
void popStack(SqStack& S);  		      //数据元素出栈 
int  emptyStack(SqStack& S);			  //判断栈是否为空 
void createBiTree(Tree& T);				  //创建并添加二叉树信息,录入方式为根左右 
void inTraverseByRecur(Tree& T);		  //递归方式实现中序遍历二叉树
void inTraverseByNotRecur(Tree& T,SqStack& S);  //非递归方式实现中序遍历二叉树()
elemType getTop(SqStack& S);              //返回栈顶元素 

void initStack(SqStack& S)
{ 
	S.base=(elemType*)malloc(STACK_INIT_SIZE * sizeof(elemType));
	if(!S.base)  exit(1);
	S.top=S.base;
	S.stackSize=STACK_INIT_SIZE;  
} 

void pushStack(SqStack& S,elemType data)
{
	if(S.top-S.base>=S.stackSize) //栈满,扩充容量 
	{
		S.base=(elemType*)realloc(S.base,(S.stackSize+STACK_INC_SIZE) * sizeof(elemType));
		if(!S.base)  exit(1);
		S.top=S.base+S.stackSize; //栈顶改变
		S.stackSize+=STACK_INC_SIZE;
	}
	*S.top=data;
	S.top++;
}

void popStack(SqStack& S)
{
	if(S.top!=S.base)
	{
		S.top--;
	} 
}

int emptyStack(SqStack& S)
{
	//栈空则返回0 
	if(S.base==S.top)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

elemType getTop(SqStack& S)
{
	return *(S.top-1);
}	

void createBiTree(Tree& T)
{
	ElementType ch;
	cin>>ch;
	if(ch=='#') T=NULL;
	else
	{
		//if(!(T=(TreeNode*)malloc(sizeof(TreeNode))))
		if(!(T=(Tree)malloc(sizeof(TreeNode))))
		{
			cout<<"malloc fail"<<endl;
			exit(0);
		}
		T->data=ch;
		createBiTree(T->lchild);
		createBiTree(T->rchild);
	}
}

//实现递归方式的中序遍历
void inTraverseByRecur(Tree& T)
{
	//-+a##*b##-c##d##/e##f##
	if(T)
	{
		inTraverseByRecur(T->lchild);
		cout<<T->data;
		inTraverseByRecur(T->rchild);
	}
} 

//实现非递归方式的中序遍历
void inTraverseByNotRecur(Tree& T,SqStack& S)
{
	Tree p;
	p=T;
	//若栈为空,emptyStack(S)返回为0 
	while(p||emptyStack(S))  //只有当结点为空,栈也为空时退出循环 
	{
		while(p)   //结点不为空时,一直找左孩子 
		{
			pushStack(S,p);
			p=p->lchild;
		}		   
		//找不到左孩子时,若栈也不为空,则栈顶元素出栈,将栈顶元素的右孩子再作为根结点,继续找左孩子
		//这样持续下去最终会按照非递归的方式输出左根右 
		if(emptyStack(S))		
		{
			p=getTop(S);	 
			cout<<p->data;
			popStack(S);
			p=p->rchild;
		}
	}
}

int main()
{
	SqStack S;     			//定义栈S 
	Tree T1;	   			//定义二叉树的根结点 
	initStack(S);  			//初始化栈S 
	createBiTree(T1);		//创建并添加二叉树信息
	inTraverseByRecur(T1);  //递归方式中序遍历二叉树 
	cout<<endl; 
	inTraverseByNotRecur(T1,S);//非递归方式中序遍历二叉树 
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值