二叉树非递归遍历法

二叉树的结构声明:

#include 
#include
#include 
using namespace std;

typedef struct node{
    char data;
    struct node *lchild;
	struct node *rchild;
}BinTree;

typedef struct node1{
    BinTree *btnode;
    bool isFirst;
}BTNode;

二叉树的创建:

void creatBinTree(char *s,BinTree *&root)  //创建二叉树,s为形如A(B,C(D,E))形式的字符串 
{
    int i;
    bool isRight=false;
    stack s1;          //存放结点 
    stack s2;              //存放分隔符
    BinTree *p,*temp;
    root->data=s[0];
    root->lchild=NULL;
    root->rchild=NULL;
    s1.push(root);
    i=1;
    while(idata=s[i];
            p->lchild=NULL;
            p->rchild=NULL;
            temp=s1.top();
            if(isRight==true)    
            {
                temp->rchild=p;
                cout<data<<"的右孩子是"<lchild=p;
                cout<data<<"的左孩子是"<data;
        if(root->lchild!=NULL)
        {
            cout<<'(';
            display(root->lchild);
        }
        if(root->rchild!=NULL)
        {
            cout<<',';
            display(root->rchild);
            cout<<')';
        }
    }
}

二叉树的前序遍历:

原理:就是利用栈的思想,先一直沿左子树遍历

“实在不行”了再回溯当当前节点的根节点,

继而转向根节点的右子树,继续进行沿左子树的遍历。

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


二叉树的中序遍历:

原理:与前序遍历基本相同,不同的一点是在前序遍历中,先访问节点,再沿左子树遍历

而中序遍历中我们一般会先遍历,再访问该节点

void inOrder(BinTree *root)      //非递归中序遍历
{
    stack 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<data<<" ";
            s.pop();
            p=p->rchild;
        }
    }    
} 


二叉树的后序遍历:

原理:后序遍历的难度最大,因为其左右递归均不是严格的尾递归。

我们在非递归遍历中,访问完了左子树,不能立即访问根节点,

而应该将根节点保存起来,由保存的根节点找到右子树,

等根节点的左右子树都访问完了,我们才能访问根节点。


在具体的实现中,我们可以使用一个标志变量来标记该节点的左右子树是否都已经被访问,

如果标志值为true,说明该节点的右子树还未访问,我们可以将标志值改为false,

然后再将该节点入栈,访问右子树;

在后面会第二次遇到该节点,由于该节点的标志值已经为false,

证明该节点的左右子树都已被访问,我们可以访问该节点并将其出栈。

void postOrder(BinTree *root)    //非递归后序遍历
{
    stack s;
    BinTree *p=root;
    BTNode *temp;
    while(p!=NULL||!s.empty()){
        while(p!=NULL){              //沿左子树一直往下搜索,直至出现没有左子树的结点 
            BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
            btn->btnode=p;
            btn->isFirst=true;
            s.push(btn);
            p=p->lchild;
        }
        if(!s.empty()){
            temp=s.top();
            s.pop();
            if(temp->isFirst==true){     //表示是第一次出现在栈顶 
                temp->isFirst=false;
                s.push(temp);
                p= temp -> btnode -> rchild;    
            }
            else{                        //第二次出现在栈顶 
                cout<btnode->data<<" ";
                p=NULL;
            }
        }
    }    
} 


你可能感兴趣的:(数据结构,C++,数据结构,二叉树,遍历,结构)