二叉树前序、中序、后续遍历的非递归算法

本文详细解析了二叉树前序、中序、后序非递归遍历算法,通过栈操作实现遍历过程,适用于理解和实现二叉树的非递归遍历方法。

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

题目描述:二叉树前序、中序、后序遍历的非递归算法

思想: 二叉树前序、中序、后续非递归遍历需要栈来完成。

 前序遍历非递归遍历:由于前序遍历二叉树顺序是根-左-右,所以在非递归遍历时,先让根结点入栈,然后出栈一个结点p并访问,然后判断p结点的右孩子结点是否存在,若存在则右孩子结点入栈,然后判断p结点的左孩子结点是否存在,如存在p的左孩子结点入栈。如上循环,直到栈为空为止。

 中序遍历非递归遍历:由于中序遍历二叉树顺序是左-根-右,所以在非递归遍历时先扫描(不是访问)将根结点的所有左结点入栈,  然后出栈一个结点p(显然p结点无左孩子或左孩子结点已经被访问过)并访问p结点,然后访问扫描p结点的右孩子结点,若存在将其进栈,在扫描p结点右孩子结点的所有左节点并一一进栈,若不存在继续出栈一个结点,如上循环直到栈空为止。

 后续遍历非递归遍历:由于后续遍历二叉树顺序是左-右-根,所以用栈来存储结点必须分清返回根结点时是从左子树返回还是从右子树返回。所以要使用辅助指针pre,让其指向最近访问过的结点。 在非递归遍历时先扫描将根结点的所有左结点入栈,然后取栈顶结点p,判断p结点的右孩子结点是否等于pre(之前访问过的结点,这样做的目的就是分清是从左子树返回的还是从右子树返回),若不等于则p结点的右孩子结点入栈然后将其结点的所有左结点一一入栈,若等于则出栈当前结点p,用pre指向p,然后继续去栈顶结点。如上循环,直到栈为空为止。

算法代码:

void preorder(BiTree T){   //二叉树非递归前序遍历
	stack s;
	BiTree p ;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	s.data[++s.top] = T;//根结点先入栈
	while (s.top>=0)
	{
		p = s.data[s.top--]; //出栈
		cout << p->data << "\t";
		if (p->rchild != NULL){
			s.data[++s.top] = p->rchild;
		}
		if (p->lchild != NULL){
			s.data[++s.top] = p->lchild;

		}
	}
}
void inorder(BiTree T){    //二叉树非递归中序遍历
	stack s;
	BiTree p=T;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	while (p!=NULL || s.top>=0)
	{
		if (p != NULL){
			s.data[++s.top] = p;
			p = p->lchild;
		}
		else{
			p = s.data[s.top--];   //出栈
			cout << p->data << "\t";
			p = p->rchild;
		}
	}
}
void postorder(BiTree T){  //二叉树非递归后序遍历
	stack s;
	BiTree p = T, pre=NULL;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	while (p!=NULL || s.top>=0)
	{
		if (p != NULL){
			s.data[++s.top] = p; //进栈
			p = p->lchild;
		}
		else{
			p = s.data[s.top];  //取栈顶结点
			if (p->rchild != pre &&p->rchild != NULL){
				p = p->rchild;
			}
			else
			{
				p = s.data[s.top--];  //出栈
				cout << p->data << "\t";
				pre = p;
				p = NULL;
			}
		}
	}
}

样本:

                                  

二叉树先序序列:ABDEHCFIG

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef char ElemType;
#define Maxsize 30
typedef struct BiTNode{
	ElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree;
typedef struct stack{  //辅助栈
	BiTree data[Maxsize];
	int top = -1;
}stack;
void preorder(BiTree T){   //二叉树非递归前序遍历
	stack s;
	BiTree p ;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	s.data[++s.top] = T;//根结点先入栈
	while (s.top>=0)
	{
		p = s.data[s.top--]; //出栈
		cout << p->data << "\t";
		if (p->rchild != NULL){
			s.data[++s.top] = p->rchild;
		}
		if (p->lchild != NULL){
			s.data[++s.top] = p->lchild;

		}
	}
}
void inorder(BiTree T){    //二叉树非递归中序遍历
	stack s;
	BiTree p=T;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	while (p!=NULL || s.top>=0)
	{
		if (p != NULL){
			s.data[++s.top] = p;
			p = p->lchild;
		}
		else{
			p = s.data[s.top--];   //出栈
			cout << p->data << "\t";
			p = p->rchild;
		}
	}
}
void postorder(BiTree T){  //二叉树非递归后序遍历
	stack s;
	BiTree p = T, pre=NULL;
	if (T == NULL){
		cout << "二叉树为空";
		exit(0);
	}
	while (p!=NULL || s.top>=0)
	{
		if (p != NULL){
			s.data[++s.top] = p; //进栈
			p = p->lchild;
		}
		else{
			p = s.data[s.top];  //取栈顶结点
			if (p->rchild != pre &&p->rchild != NULL){
				p = p->rchild;
			}
			else
			{
				p = s.data[s.top--];  //出栈
				cout << p->data << "\t";
				pre = p;
				p = NULL;
			}
		}
	}
}
void createBiTree(BiTree &T){
	T = (BiTree)malloc(sizeof(BiTree));
	cin >> T->data;
	if (T->data == '#'){
		T = NULL;
		return;
	}
	createBiTree(T->lchild);
	createBiTree(T->rchild);
}
int main(){
	BiTree T;
	cout << "输入二叉树的前序序列以#代表空(创建二叉树):";
	createBiTree(T);
	cout << "\n"<<"二叉树的前序非递归遍历序列:";
	preorder(T);
	cout <<"\n"<< "二叉树的中序非递归遍历序列:";
	inorder(T);
	cout << "\n" << "二叉树的后序非递归遍历序列:";
	postorder(T);
	system("pause");
	return 0;
}

二叉树中序序列:DBHEAFICG

二叉树后序序列:DHEBIFGCA

完整代码:

 

结果显示:

下面是C语言实现二叉树遍历后序遍历的递归算法和非递归算法的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAXSIZE 100 // 二叉树结构体 typedef struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; } TreeNode, *PtrToNode; // 结构体 typedef struct Stack { PtrToNode data[MAXSIZE]; int top; } Stack, *PtrToStack; // 初始化 void InitStack(PtrToStack S) { S->top = -1; } // 判断是否为空 bool IsEmpty(PtrToStack S) { return S->top == -1; } // 判断是否已满 bool IsFull(PtrToStack S) { return S->top == MAXSIZE - 1; } // void Push(PtrToStack S, PtrToNode X) { if (IsFull(S)) { printf("已满\n"); return; } S->data[++S->top] = X; } // 出 PtrToNode Pop(PtrToStack S) { if (IsEmpty(S)) { printf("已空\n"); return NULL; } return S->data[S->top--]; } // 中遍历递归算法 void InOrderTraversal(PtrToNode root) { if (root) { InOrderTraversal(root->left); printf("%d ", root->data); InOrderTraversal(root->right); } } // 中遍历非递归算法 void InOrderTraversal2(PtrToNode root) { Stack S; InitStack(&S); PtrToNode p = root; while (p || !IsEmpty(&S)) { if (p) { Push(&S, p); p = p->left; } else { p = Pop(&S); printf("%d ", p->data); p = p->right; } } } // 后序遍历递归算法 void PostOrderTraversal(PtrToNode root) { if (root) { PostOrderTraversal(root->left); PostOrderTraversal(root->right); printf("%d ", root->data); } } // 后序遍历非递归算法 void PostOrderTraversal2(PtrToNode root) { Stack S; InitStack(&S); PtrToNode p = root; PtrToNode r = NULL; while (p || !IsEmpty(&S)) { if (p) { Push(&S, p); p = p->left; } else { p = S.data[S.top]; if (p->right && p->right != r) { p = p->right; Push(&S, p); p = p->left; } else { p = Pop(&S); printf("%d ", p->data); r = p; p = NULL; } } } } // 创建二叉树 void CreateTree(PtrToNode *root) { int data; scanf("%d", &data); if (data == -1) { *root = NULL; } else { *root = (PtrToNode)malloc(sizeof(TreeNode)); (*root)->data = data; CreateTree(&((*root)->left)); CreateTree(&((*root)->right)); } } int main() { PtrToNode root; printf("请输二叉树前序遍历列,-1表示空节点:\n"); CreateTree(&root); printf("中遍历递归算法:"); InOrderTraversal(root); printf("\n中遍历非递归算法:"); InOrderTraversal2(root); printf("\n后序遍历递归算法:"); PostOrderTraversal(root); printf("\n后序遍历非递归算法:"); PostOrderTraversal2(root); printf("\n"); return 0; } ``` 其中,CreateTree函数用于创建二叉树,InOrderTraversal和PostOrderTraversal函数分别是中遍历后序遍历的递归算法,InOrderTraversal2和PostOrderTraversal2函数分别是中遍历后序遍历非递归算法。在非递归算法中,我们使用了来模拟递归的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值