您的位置:首页 > 其它

二叉树的三种遍历,递归与非递归

2012-08-08 13:50 302 查看
1.先序遍历

#include "stdafx.h"
#include<iostream>
using namespace std;
typedef struct BTreeNode
{
int data;
struct BTreeNode *lchild,*rchild;
}BTree;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
void PreOrder(BTree *b)
{
if(b!=NULL)
{
printf("%c ",b->data);
PreOrder(b->lchild);
PreOrder(b->rchild);
}
}


2.中序遍历

void InOrder(BTree *b)
{
if(b!=NULL)
{
InOrder(b->lchild);
printf("%c ",b->data);
InOrder(b->rchild);
}
}


3.后序遍历

void PostOrder(BTree *b)
{
if(b!=NULL)
{
PostOrder(b->lchild);
PostOrder(b->rchild);
printf("%c ",b->data);
}
}


4.使用栈的非递归遍历

非递归实现

根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:

对于任一结点P:

1)访问结点P,并将结点P入栈;

2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

3)直到P为NULL并且栈为空,则遍历结束

void preOrder2(BinTree *root)     //非递归前序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}


5.使用栈的中序

void inOrder2(BinTree *root)      //非递归中序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}


6.后序非递归

思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

void postOrder3(BinTree *root)     //非递归后序遍历
{
stack<BinTree*> s;
BinTree *cur;                      //当前结点
BinTree *pre=NULL;                 //前一次访问的结点
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}


最常用版本:

#include "stdafx.h"
#include<iostream>
using namespace std;
typedef struct BTreeNode
{
int data;
struct BTreeNode *lchild,*rchild;
}BTree;
typedef struct stacknode
{
BTree *node;
int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问
}stack;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
void PostOrder2(BTree *b)
{
stack s[100];
int top=-1;
stack temp;//暂存结点信息
while(b||top>-1)
{
while(b)
{
temp.node=b;
temp.tag=0;//左结点已访问
s[++top]=temp;
b=b->lchild;
}
while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点
//b = s[top --].node;
//cout << b->val << ' ';
/*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top)
如果要写这两行而不写下面那句的话,要采用do{}while(top);*/
cout << s[top --].node->data<< ' ';
}
if(top!=-1)
{
s[top].tag= 1; //右结点已访问
b = s[top].node;
b = b->rchild;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: