二叉树的先序、中序、后序遍历,采用非递归实现。
非递归实现的一个基本思路:在遍历的过程中要用栈来保存遍历中经过的结点。
#include<stdio.h>
#include<stdlib.h>
typedef char DataType;
//定义二叉树类型的节点
typedef struct BTnode{
DataType data;//数据域
struct BTnode* lchild,*rchild;//左孩子和右孩子
int isFirst;//后序遍历用到,用于表示是不是第一次入栈
}BTree;
//创建二叉树,以先序的方式输入,如果左孩子或右孩子为空,则输入#
/*
例子 A 输入为:ABD##E##CF###
/ \
B C
/ \ /
D E F
*/
void createBTree(BTree * &t)
{
char c;
c=getchar();
if(c=='#')
t=NULL;
else
{
t=(BTree*)malloc(sizeof(BTree));
t->data=c;
createBTree(t->lchild);//创建左子树
createBTree(t->rchild);//创建右子树
}
}
/*
根据先序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,
因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;
当访问完其左子树时,再访问它的右子树。因此其处理过程如下:
对于任一结点q:
1)访问结点q,并将结点q入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,
并将栈顶结点的右孩子置为当前的结点q,循环至1);
若不为空,则将q的左孩子置为当前的结点q;
3)直到栈为空,则遍历结束。
*/
//非递归先序遍历
void preOrder(BTree * root)
{
BTree * q,*s[100];
q=root;
int top=0;
while(1)
{
while(NULL!=q)
{
printf("%c ",q->data);//访问q结点
top++;
s[top]=q;
q=q->lchild;
}
if(0!=top)
{
q=s[top];//出栈
top--;
q=q->rchild;//搜索右子树
}
else
break;
}
}
/*
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,
然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,
然后按相同的规则访问其右子树。因此其处理过程如下:
对于任一结点P,
1)若其左孩子不为空,则将q入栈并将P的左孩子置为当前的q,然后对当前结点q再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的q置为栈顶结点的右孩子;
3)直到栈为空则遍历结束
*/
//非递归中序遍历
void inOrder(BTree * root)
{
BTree * q,*s[100];//数组的每个元素是链表结点,s当做栈
q=root;
int top=0;//栈顶指针
while(1)
{
while(NULL!=q)
{
top++;
s[top]=q; //先把左子树的每个结点入栈
q=q->lchild;
}
if(0!=top)
{
q=s[top];//左子树全部入栈后开始出栈
top--;
printf("%c ",q->data);//访问出栈的根节点
q=q->rchild; //搜索右子树
}
else
break;//栈空时停止
}
}
/*
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,
要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,
这就为流程的控制带来了难题。下面介绍两种思路。
第一种思路:
对于任一结点q,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,
但是此时不能将其出栈并访问,因为其右孩子还没被访问。所以接下来按照相同的规则对其右子树进行相同的处理,
当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。
可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。
因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
*/
//非递归后序遍历 方法一
void postOrder1(BTree * root)
{
BTree * q,*s[100];
q=root;
int top=0;
while(1)
{
while(NULL!=q)//沿左子树一直往下搜索,直至出现没有左子树的结点
{
top++;
q->isFirst=1;
s[top]=q;
q=q->lchild;
}
if(0!=top)
{
q=s[top];
top--;
if(q->isFirst)//第一次出现在栈顶
{
q->isFirst=0;
top++;
q=q->rchild;
}
else//第二次出现在栈顶
{
printf("%c ",q->data);
q=NULL;
}
}
else
break;
}
}
/*
第二种思路:
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点q,先将其入栈。
如果q不存在左孩子和右孩子,则可以直接访问它;或者q存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,
则同样可以直接访问该结点。若非上述两种情况,则将q的右孩子和左孩子依次入栈,
这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
*/
//非递归后序遍历 方法二
void postOrder2(BTree * root)
{
BTree * q,*s[100],*pre=NULL;//pre 前一次访问的结点
q=root;
int top=0;
s[++top]=q;
while(1)
{
q=s[top];
//如果当前结点没有孩子结点或者孩子节点都已被访问过
if((q->lchild==NULL&&q->rchild==NULL)||(pre!=NULL&&(pre==q->lchild||pre==q->rchild)))
{
printf("%c ",q->data);
top--;
pre=q;
}
else
{
if(NULL!=q->rchild)
s[++top]=q->rchild;//右孩子先入栈
if(NULL!=q->lchild)
s[++top]=q->lchild;
}
if(top==0)
break;
}
}
int main()
{
BTree *root;
createBTree(root);
preOrder(root);
printf("\n");
inOrder(root);
printf("\n");
postOrder1(root);
printf("\n");
postOrder2(root);
printf("\n");
return 0;
}
分享到:
相关推荐
本资料“数据结构 二叉树三种遍历的非递归算法(背诵版)”着重介绍了二叉树的三种主要遍历方法——前序遍历、中序遍历和后序遍历的非递归实现。 **前序遍历**: 前序遍历的顺序是:根节点 -> 左子树 -> 右子树。非...
前序遍历是二叉树遍历的一种方式,其顺序为“根节点 -> 左子树 -> 右子树”。具体而言,在遍历过程中,首先访问根节点,然后递归地遍历左子树,最后递归地遍历右子树。对于非递归的前序遍历,通常会利用栈来辅助实现...
二叉树三种遍历非递归算法 二叉树是一种常用的数据结构,它广泛应用于计算机科学和软件工程中。二叉树的遍历是指对二叉树中的每个结点进行访问的过程。常见的二叉树遍历方法有三种:先序遍历、中序遍历和后序遍历。...
这是数据结构中二叉树的后序遍历的非递归算法的源代码。
二叉树的递归遍历、非递归遍历和层次遍历
本文将详细介绍如何用C语言实现二叉树的中序遍历(非递归方式),并给出具体的代码示例。 #### 基本概念 - **二叉树**:每个节点最多有两个子节点的数据结构。 - **中序遍历**:遍历顺序为“左-根-右”,即先遍历...
使用C++模板、类的技术实现了二叉树的中序遍历,在BC3.1已经测试成功
用C++写的,包括二叉树的构建,二叉树的先序遍历、中序遍历和后序遍历非递归算法。
用C++写的二叉树先序遍历、中序遍历和后序遍历非递归算法
中序遍历是一种常用的二叉树遍历算法,它首先遍历左子树,然后遍历根节点,最后遍历右子树。在这个代码中,我们使用栈来实现非递归中序遍历算法。 int InOrderTraverse(BiTree T){ BiTree p; sqstack L; ...
#### 三、二叉树遍历的类型 二叉树的遍历主要有三种类型: 1. **前序遍历**:访问顺序为“根节点 -> 左子树 -> 右子树”。 2. **中序遍历**:访问顺序为“左子树 -> 根节点 -> 右子树”。 3. **后序遍历**:访问...
常见的二叉树遍历方法有三种:先序遍历、中序遍历和后序遍历。通常我们使用递归的方式来实现这三种遍历,但递归方法在某些情况下可能会导致栈溢出或者效率较低。因此,非递归算法的实现变得很有必要,特别是在面试或...
### 前序遍历非递归算法 前序遍历的顺序是:根节点→左子树→右子树。在非递归实现中,我们利用栈来辅助完成这一过程。首先,将根节点压入栈中,然后持续访问当前节点并将其左孩子压入栈,直到遇到空节点。此时,从...
1. 先序遍历非递归算法 先序遍历是一种常见的二叉树遍历算法。它的遍历顺序是:根节点 -> 左子树 -> 右子树。下面是先序遍历的非递归算法实现: ```c void PreOrderUnrec(Bitree t) { SqStack s; StackInit(s); ...
C语言二叉树遍历前序非递归算法,简单易懂,正确无误
本篇文章将深入探讨二叉树的三种遍历方法:递归遍历(前序、中序、后序)、非递归遍历以及层次遍历。 1. **递归遍历**: - **前序遍历**:先访问根节点,然后递归地遍历左子树,最后遍历右子树。用公式表示为:根-...
在本主题中,我们将深入探讨二叉树的三种主要遍历方法:中序遍历、前序遍历和后序遍历,以及如何通过递归和非递归的方式实现这些遍历。 首先,让我们理解递归遍历的概念。递归是一种解决问题的方法,它将问题分解为...
### 三、后序遍历非递归算法 #### 算法原理 后序遍历遵循“左子树 -> 右子树 -> 根节点”的顺序访问节点。对于非递归实现来说,后序遍历相对较为复杂,通常需要借助两个栈或者栈加标志位的方法来辅助实现。这里采用...
二叉树的三种遍历,递归与非递归,按层。适合初学者。