首页 > 代码库 > 二叉树的几种递归和非递归式遍历:

二叉树的几种递归和非递归式遍历:

二叉树的几种递归和非递归式遍历:

#include <fstream>
#include <iostream>

using namespace std;

/*
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子
前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,
但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子
时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现
在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,
则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种
情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结
点前面被访问。
*/

#define queue_len 100

struct node
{
char c;
struct node *lch,*rch;
bool flag;
node():flag(0){}
void get_c()
{
printf("%c",c);
}
};

node* set_tree();//建树
void pre_order(node* tree);//先序遍历
void in_order(node* tree);//中序遍历
void post_order(node* tree);//后序遍历
void level_order(node* tree);//层次遍历
void nr_pre_order(node* tree);//非递归先序遍历
void nr_in_order(node* tree);//非递归中序遍历
void nr_post_order_1(node* tree);//非递归后序遍历
void nr_post_order_2(node* tree);//非递归后序遍历

int main()
{
//freopen("D:\\input.in","r",stdin);
//freopen("D:\\output.out","w",stdout);
node* tree=set_tree();
printf("先序遍历:");
pre_order(tree);
puts("");
printf("中序遍历:");
in_order(tree);
puts("");
printf("后序遍历:");
post_order(tree);
puts("");
printf("层次遍历:");
level_order(tree);
puts("");
printf("先序遍历:");
nr_pre_order(tree);
puts("");
printf("中序遍历:");
nr_in_order(tree);
puts("");
printf("后序遍历:");
nr_post_order_1(tree);
puts("");
printf("后序遍历:");
nr_post_order_2(tree);
puts("");
return 0;
}
node* set_tree()
{
node* p,*s;
node* gen=new node;
gen->c=‘A‘;

gen->lch=new node;
p=gen->lch;
p->c=‘B‘;
p->rch=NULL;
p->lch=new node;
p=p->lch;
p->c=‘D‘;
p->lch=NULL;
p->rch=new node;
p=p->rch;
p->c=‘G‘;
p->lch=NULL;
p->rch=NULL;

gen->rch=new node;
p=gen->rch;
p->c=‘C‘;
p->lch=new node;
s=p->lch;
s->c=‘E‘;
s->lch=NULL;
s->rch=NULL;
p->rch=new node;
s=p->rch;
s->c=‘F‘;
s->lch=NULL;
s->rch=NULL;

return gen;
}
void pre_order(node* tree)
{
if(tree!=NULL)
{
tree->get_c();
pre_order(tree->lch);
pre_order(tree->rch);
}
}
void in_order(node* tree)
{
if(tree!=NULL)
{
in_order(tree->lch);
tree->get_c();
in_order(tree->rch);
}
}
void post_order(node* tree)
{
if(tree!=NULL)
{
post_order(tree->lch);
post_order(tree->rch);
tree->get_c();
}
}
void level_order(node* tree)
{
node* queue_1[queue_len];
int front,rear;

if(tree==NULL) return;
front=-1;
rear=0;
queue_1[rear]=tree;
while(front!=rear)
{
front++;
queue_1[front]->get_c();

if(queue_1[front]->lch!=NULL)
{
rear++;
queue_1[rear]=queue_1[front]->lch;
}
if(queue_1[front]->rch!=NULL)
{
rear++;
queue_1[rear]=queue_1[front]->rch;
}
}
}
void nr_pre_order(node* tree)
{
node* stack_1[queue_len];
int top=-1;

if(tree==NULL) return;
node* p=tree;
while(p!=NULL||top!=-1)
{
while(p!=NULL)
{
p->get_c();
stack_1[++top]=p;
p=p->lch;
}
if(top==-1) return;
p=stack_1[top--]->rch;
}
}
void nr_in_order(node* tree)
{
node* stack_1[queue_len];
int top=-1;

if(tree==NULL) return;
node* p=tree;
while(p!=NULL||top!=-1)
{
while(p!=NULL)
{
stack_1[++top]=p;
p=p->lch;
}
if(top==-1) return;
stack_1[top]->get_c();
p=stack_1[top--]->rch;
}
}
void nr_post_order_1(node* tree)
{
node* stack_1[queue_len];
int top=-1;

if(tree==NULL) return;
node* p=tree;
while(p!=NULL||top!=-1)
{
while(p!=NULL)
{
stack_1[++top]=p;
p=p->lch;
}
if(top==-1) return;
p=stack_1[top];
if(p->flag==0) {p->flag=1;p=p->rch;}
else { p->get_c(),top--;p=NULL;}
}
}
void nr_post_order_2(node* tree)
{
node* stack_1[queue_len];
int top=0;

if(tree==NULL) return;
node* p=tree;
while(top!=-1)
{
p=stack_1[top];
if((p->lch==NULL||p->lch->flag==0)&&(p->rch==NULL||p->rch->flag==0))
{
p->get_c();
p->flag=0;
top--;
}
else
{
if(p->rch!=NULL)
{
stack_1[++top]=p->rch;
}
if(p->lch!=NULL)
{
stack_1[++top]=p->lch;
}
}
}
}

二叉树的几种递归和非递归式遍历: