二叉树的非递归遍历(C语言实现)

时间:2022-07-20 10:18:35

上一篇讨论了二叉树的的递归遍历,这一次讨论二叉树的三种非递归遍历

二叉树的非递归遍历采用栈实现,首先给出二叉树和栈的定义

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef char lElemType;
typedef struct BiTNode {
	lElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
typedef BiTree SElemType;
typedef struct {
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

接下来是建立一个栈的过程

int  InitStack(SqStack &S)//建立一个栈
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!(S.base)) exit(-1);
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return 0;
}
int Push(SqStack &S,SElemType e)//将元素e插入栈中
{
	if (S.top - S.base >= S.stacksize)
	{
		if(!(S.base = (SElemType*)realloc(S.base, (STACK_INIT_SIZE + STACKINCREMENT) * sizeof(SElemType))))
		exit(-1);
		S.top = S.base + STACKINCREMENT;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
	return 0;
}
int Pop(SqStack &S, SElemType  &e)//出栈,将栈顶元素赋值给e返回
{
	if (S.base == S.top)
		return false;
	e =*--S.top;
	return 0;
}
int StackEmpty(SqStack &S)//判定栈是否为空
{
	if (S.base == S.top)
	{
		return true;
	}
	else
		return false;
}
int GetTop(SqStack S, BiTree &e)//取栈顶元素赋值给e
{
	if (S.top == S.base) return false;
	e = *(S.top-1);
	return 0;
}

接下来通过先序遍历建立一个如下的二叉树

二叉树的非递归遍历(C语言实现)

代码如下:

void CreateBiTree(BiTree &T)//先序建立一棵二叉树
{
	lElemType ch;
	cin >> ch;
	if (ch == '*') T = NULL;//输入*表示二叉树的该节点为空
	else {
		if (!(T = (BiTNode*)malloc(sizeof(BiTNode))))
		exit(-1);
		T->data = ch;
		CreateBiTree(T->lchild);
		CreateBiTree(T->rchild);

	}
}

二叉树的先序,中序非递归遍历的唯一不同是出栈的时间

先序遍历:①首先访问根节点是否为空,则入栈→输出栈顶元素→当前节点的左子树入栈

                 ②当左子树为空,则栈顶元素出栈,转向该节点的右子树 

                 ③全部元素出栈以后,结束循环

中序遍历:①入栈→当前节点的左子树入栈

                 ②当左子树为空,则栈顶元素出栈,输出栈顶元素→转向该节点的右子树

                ③栈为空时,结束循环

int PreOrderTraverse2(BiTree T)//前序非递归遍历第一种方法
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	while (p || !StackEmpty(S))
	{
		if (p) {
			Push(S, p);
			cout << T->data;
			p = p->lchild;
		}
		else
		{
			Pop(S, p);
			p = p->rchild;
		}
	}
	cout << endl;
	return 0;
}
 int PreOrderTraverse3(BiTree T)//前序遍历得第二种方法
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	Push(S, p);
	while (!StackEmpty(S))
	{
		while (GetTop(S, p) && p)
		{
			cout << p->data;
			Push(S, p->lchild);
	    }
		Pop(S, p);
		if (!StackEmpty(S))
		{
			Pop(S, p);
			Push(S, p->rchild);
		}
	}
	return 0;
}
int InOrederTraverse2(BiTree T)//中序非递归遍历
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	while (p || !StackEmpty(S))
	{
		if (p) {
			Push(S, p);
			p = p->lchild;
		}
		else
		{
			Pop(S, p);
			cout << p->data;
			p = p->rchild;
		}
	}
	cout << endl;
	return 0;
}

链表的后序非递归遍历:p指向当前的节点,cur指向前一个节点

                                   ①根节点入栈,如果栈不为空,则判断栈顶元素节点的左右节点是否为空,同时判断

                                      前一个节点是否是当前节点的左孩子或者右孩子

                                   ②如果①为真,则输出当前节点且栈顶元素出栈,同时令cur等于当前节点

                                   ③如果①为假,则当前节点的孩子节点入栈

                                   ④当栈为空时,退出循环

注意:后序遍历入栈时应该右节点先入栈

int PostOrderTraverse2(BiTree T)//后序非递归遍历
{
	SqStack  S;
	InitStack(S);
	BiTree p = T, cur = NULL;
	Push(S, p);
	while (!StackEmpty(S))//栈不为空
	{
		GetTop(S, p);
		if ((p->lchild == NULL && p->rchild == NULL) || (cur == p->lchild || cur == p->rchild))//
		{
			cout << p->data;
			Pop(S, p);
			cur = p;
		}
		else {
			if (p->rchild != NULL)
				Push(S, p->rchild);
			if (p->lchild != NULL)
				Push(S, p->lchild);
		}
	}
	return 0;
}

整个代码如下:

#include<iostream>
#include<iomanip>
using namespace std;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef char lElemType;
typedef struct BiTNode {
	lElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
typedef BiTree SElemType;
typedef struct {
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;
int  InitStack(SqStack &S)//建立一个栈
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!(S.base)) exit(-1);
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return 0;
}
int Push(SqStack &S,SElemType e)//将元素e插入栈中
{
	if (S.top - S.base >= S.stacksize)
	{
		if(!(S.base = (SElemType*)realloc(S.base, (STACK_INIT_SIZE + STACKINCREMENT) * sizeof(SElemType))))
		exit(-1);
		S.top = S.base + STACKINCREMENT;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
	return 0;
}
int Pop(SqStack &S, SElemType  &e)//出栈,将栈顶元素赋值给e返回
{
	if (S.base == S.top)
		return false;
	e =*--S.top;
	return 0;
}
int StackEmpty(SqStack &S)//判定栈是否为空
{
	if (S.base == S.top)
	{
		return true;
	}
	else
		return false;
}
int GetTop(SqStack S, BiTree &e)//取栈顶元素赋值给e
{
	if (S.top == S.base) return false;
	e = *(S.top-1);
	return 0;
}
void CreateBiTree(BiTree &T)//先序建立一棵二叉树
{
	lElemType ch;
	cin >> ch;
	if (ch == '*') T = NULL;
	else {
		if (!(T = (BiTNode*)malloc(sizeof(BiTNode))))
		exit(-1);
		T->data = ch;
		CreateBiTree(T->lchild);
		CreateBiTree(T->rchild);

	}
}
int PreOrderTraverse1(BiTree T)//先序递归遍历
{
	if (T) {
		cout<< T->data;
		PreOrderTraverse1(T->lchild);
		PreOrderTraverse1(T->rchild);
		return 0;
	}
	else
		return false;
}
int InOrderTraverse1(BiTree T)//中序递归遍历
{
	if (T) {
		InOrderTraverse1(T->lchild);
		cout<< T->data;
		InOrderTraverse1(T->rchild);
		return true;
	}
	else
		return false;
}
int PostOrderTraverse1(BiTree T)//后续递归遍历
{
	if (T) {
		PostOrderTraverse1(T->lchild);
		PostOrderTraverse1(T->rchild);
		cout<< T->data;
		return true;
	}
	else
		return false;
}
int PreOrderTraverse2(BiTree T)//前序非递归遍历第一种方法
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	while (p || !StackEmpty(S))
	{
		if (p) {
			Push(S, p);
			cout << T->data;
			p = p->lchild;
		}
		else
		{
			Pop(S, p);
			p = p->rchild;
		}
	}
	cout << endl;
	return 0;
}
int PreOrderTraverse3(BiTree T)//前序遍历得第二种方法
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	Push(S, p);
	while (!StackEmpty(S))
	{
		while (GetTop(S, p) && p)
		{
			cout << p->data;
			Push(S, p->lchild);
	    }
		Pop(S, p);
		if (!StackEmpty(S))
		{
			Pop(S, p);
			Push(S, p->rchild);
		}
	}
	return 0;
}
int PostOrderTraverse2(BiTree T)
{
	SqStack  S;
	InitStack(S);
	BiTree p = T, cur = NULL;
	Push(S, p);
	while (!StackEmpty(S))
	{
		GetTop(S, p);
		if ((p->lchild == NULL && p->rchild == NULL) || (cur == p->lchild || cur == p->rchild))
		{
			cout << p->data;
			Pop(S, p);
			cur = p;
		}
		else {
			if (p->rchild != NULL)
				Push(S, p->rchild);
			if (p->lchild != NULL)
				Push(S, p->lchild);
		}
	}
	return 0;
}
int InOrederTraverse2(BiTree T)//中序非递归遍历
{
	SqStack S;
	InitStack(S);
	BiTree p = T;
	while (p || !StackEmpty(S))
	{
		if (p) {
			Push(S, p);
			p = p->lchild;
		}
		else
		{
			Pop(S, p);
			cout << p->data;
			p = p->rchild;
		}
	}
	cout << endl;
	return 0;
}

int main()
{
	BiTree T;
	CreateBiTree(T);
	cout << "先序递归遍历:";
	PreOrderTraverse1(T);
	cout << "\n中序递归遍历:";
	InOrderTraverse1(T);
	cout << "\n后序递归遍历:";
	PostOrderTraverse1(T);
	cout << endl;
	cout << "先序非递归遍历:";
	PreOrderTraverse1(T);
	cout << "\n中序非递归遍历:";
	InOrederTraverse2(T);
	cout << "\n后续非递归遍历:";
	PostOrderTraverse2(T);
	system("pause");
	return 0;
}

运行结果是:

二叉树的非递归遍历(C语言实现)