二叉树的非递归遍历

#include <iostream>
#include <stack>
using namespace std;
typedef struct node
{
    int data ;                 //节点信息
    struct node * leftChild ;  //左孩子
    struct node * rightChild ; //右孩子
}BiTreeNode,*BiTree;

/*
    向树中添加新节点,建立查找二叉树
*/
void addTreeNode(BiTree &T,int value)
{
    if(NULL == T)
    {
        T = new BiTreeNode ;
        T->leftChild = NULL ;
        T->rightChild = NULL ;
        T->data = value ;
    }
    else
    {
        if(T->data  > value)
        {
            addTreeNode(T->leftChild,value) ;
        }
        else if(T->data < value)
        {
            addTreeNode(T->rightChild,value) ;
        }
        else
        {
            cout<<"There has "<<value<<" in the tree!"<<endl;
        }//end if( > <value)
    }//end if(NULL == T)
}//end of addTreeNode
/*
    创建树
*/
void buildTree(BiTree &T)
{
    int b[] = {4,3,1,2,5,6,9,8} ;
    for(int i = 0 ;i< sizeof(b)/sizeof(int);++i)
        addTreeNode(T,b[i]) ;
}

//递归的前序遍历
void qianxubianli(BiTree T)
{
    if(NULL == T)
        return ;
    else
    {
        cout<<T->data<<" ";
        if(NULL !=T->leftChild)
            qianxubianli(T->leftChild) ;
        if(NULL != T->rightChild)
            qianxubianli(T->rightChild) ;
    }
}

//非递归前序遍历
//需要先压栈节点的右子树,在压栈左子树;
//因为前序遍历是先访问节点信息,在访问左子树,其次右子树;由于栈是后进后//出。所以应该先压栈右子树,再压栈左子树。
void qianxubianli2(BiTree T)
{
    stack<BiTreeNode*> s ;
    s.push(T) ;
    while(!s.empty())
    {
        BiTreeNode* t = s.top() ;
        s.pop() ;
        cout<<t->data<<" " ;        //访问节点信息
        if(NULL != t->rightChild)   //先将右孩子压栈
            s.push(t->rightChild) ;
        if(NULL != t->leftChild)     //再将左孩子压栈
            s.push(t->leftChild) ;
    }
}
//递归的中序遍历
void zhongxubianli(BiTree T)
{
    if(NULL==T)
        return ;
    else
    {
        if(NULL !=T->leftChild)
            zhongxubianli(T->leftChild) ;//访问左子树
        cout<<T->data <<" ";             //访问节点信息
        if(NULL != T->rightChild)        //访问右子树
            zhongxubianli(T->rightChild) ;
    }
}
//非递归中序遍历
/*
    思想:先循环遍历左子树,如果左子树不为空则压栈;当左子树为空时,且栈不为空时;访问栈顶元素p,pop栈顶元素,在访问p的右子树。
*/
void zhongxubianli2(BiTree T)
{
    stack<BiTree > s ;
    BiTree p = T ;
    while(p || !s.empty())
    {
        if(NULL!=p)      //沿着左子树一直往下搜索,直至左子树为空
        {
            s.push(p) ;
            p = p->leftChild ;//
        }
        else             //当左子树为空
        {
            p = s.top() ;          //取出栈顶元素
            s.pop() ;              //删除栈顶元素
            cout<<p->data<<" ";    //访问节点信息
            p=p->rightChild ;      //搜索该节点的右子树
        }
    }
}

//递归的后序遍历
void houxubianli(BiTree T)
{
    if(NULL == T)
        return ;
    if(NULL != T->leftChild) 
        houxubianli(T->leftChild) ;//访问节点的左子树
    if(NULL != T->rightChild)
        houxubianli(T->rightChild) ;//访问节点的右子树
    cout<<T->data<<" " ;            //访问节点的信息
}
/*
 第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,
 直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,
 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,
 当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。
 这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,
 只有在第二次出现在栈顶时,才能访问它。
 因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
 typedef struct node1
 {
    BinTree *btnode;
    bool    isFirst;//标记
 }BTNode;
void postOrder2(BinTree *root)    //非递归后序遍历
{
    stack<BTNode*> 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<<temp->btnode->data<<" ";
                p=NULL;
            }
        }
    }    
}
*/
/*
第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,
因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,
则可以直接访问它;或者P存在左孩子或者右孩子,
但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候
,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
*/
//非递归后序遍历 
void houxubianli2(BiTree T)
{
    stack<BiTree > s ;
    BiTree cur,pre=NULL;
    s.push(T) ;
    while( !s.empty())
    {
        cur = s.top() ;
        //记录上一个节点是否已经访问过
        //如果当前节点没有左右子节点,或者它的子节点已经被访问过
        if((cur->leftChild == NULL && cur->rightChild == NULL)||(pre != NULL &&(pre == cur->leftChild || pre== cur->rightChild)))
        {
            cout<<cur->data<<" " ; //访问节点信息
            s.pop() ;
            pre = cur ;            //记录当前访问的节点
        }
        else
        {
            if(cur->rightChild!=NULL)
                s.push(cur->rightChild) ;//访问右子树
            if(cur->leftChild!=NULL)
                s.push(cur->leftChild) ;//访问左子树
        }
    }
}

int main()
{
    BiTree T = NULL ;
    buildTree(T) ;

    cout<<"递归前序遍历:";
    qianxubianli(T) ;
    cout<<endl;
    cout<<"非递归前序遍历:";
    qianxubianli2(T) ;
    cout<<endl;

    cout<<"递归中序遍历:";
    zhongxubianli(T) ;
    cout<<endl;
    cout<<"非递归中序遍历:";
    zhongxubianli2(T) ;
    cout<<endl;

    cout<<"递归后序遍历:";
    houxubianli(T) ;
    cout<<endl;

    cout<<"非递归后序遍历:";
    houxubianli2(T) ;
    cout<<endl;
    system("pause") ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值