二叉树的9种遍历

这里着重讲解一下非递归不用栈遍历二叉树:
     我们先回忆一下递归遍历二叉树.在递归遍历二叉树的时候,我们使用系统栈做临时存储空间,记录节点的后继节点以便下一次查找.所以递归遍历所用的系统栈空间为O(h),h为二叉树的深度.一般情况下二叉树深度为lg(n),即二叉树遍历的空间复杂度为O(lg(n)),当二叉树的深度退化为n时候,即二叉树退化为链表时候,空间复杂度猛增为O(n).
     如果不用系统栈做临时存储空间,那么就一定要想一个办法,可以找到节点的后继节点,以便后续的查找.在使用自定义的栈时候就是这种思想.我们使用自定义的栈做临时存储空间,所以空间复杂度为O(h),同上,这里不再详细讲述.
    如果我们不想用栈呢,我们就一定要找到一种方法可以索引到每一个节点的后继节点.这里我们使用一种类似于线索二叉树中用到的方法,即使用指向子节点的指针为空的节点做线索,记录我们要遍历的后继节点,以便后续使用,当我们使用完成后,再把该节点重新置为空.
    这里我们要实现的是怎么才能把 指向子节点的指针为空的节点作为线索,我来画一张图,这样就更清晰了.
      第一次找到节点2,节点2的特点是右子树为空,所以记录2的后继节点为1,即把2的m_pright指向1.

     
然后设置7的右子树为2.
恢复7的右子树:

     好了,我们总结一下规律,每次遍历到一个节点pRoot时候,我们总是首先找到这样一个节点prev:
         
            prev = pRoot -> m_pLeft;
            while ( prev -> m_pRight && prev ->m_pRight != pRoot ){
                prev = prev -> m_pRight;
            }

     然后设置该节点的左子树为pRoot,这样我们就把线索记住了.

     当使用完后,我们还要把线索删除.
     我们再次遍历到该节点时候,如下列代码,我们检测是不是第二次遍历到该节点,因为我们第一次遍历到该节点是设置线索,即if里面执行的语句,我们第二次遍历该节点时候是取消线索,即else里面执行的语句.
     		if ( !prev -> m_pRight ){
                prev ->m_pRight = pRoot;
                pRoot = pRoot -> m_pLeft;
            } else {
                cout <<pRoot -> m_value<< " " ;
                prev ->m_pRight = NULL;
                pRoot = pRoot -> m_pRight;
            }

     无论先序,中序还是后序遍历,都是这种记录线索进行遍历的思想.不过后序有一点不同,后序是先输出左子树,然后右子树,最后是根.这里我们使用了一种小技巧.我们还是先看图:
对于这样一棵二叉树,后序遍历先输出9->11,4->12->13,6,2.....
大家注意到没,对于一棵二叉树的某一个左子树来说我们总是这样输出:

先输出9,

再输出11,14

再输出12,
再输出13,6,2
现在总结一下后序遍历的输出:
     1.如果该节点左子树为空,直接输出,
     2.如果第二次遍历到线索节点(第一次是设置线索,第二次是取消线索,这里的11,13都是线索节点),则倒着输出,例如输出  11,4    13,6,2    等等,具体可以看代码,很好懂的.


#include <iostream>
#include <stack>
using namespace std;


//二叉树的结构:
struct BST_node {
    int m_value;
    BST_node * m_pLeft ;
    BST_node * m_pRight ;
};


struct flage_BST_node {
    BST_node * p ;
    bool flage;
};


//利用先序和中序构造二叉树
BST_node * build_BST_core ( const int * startpre, const int * endpre,
                         const int * startmid, const int * endmid)
{
    if ( startpre> endpre || startmid > endmid ){
        return NULL ;
    }


    BST_node * root = new BST_node;
    root-> m_value = *startpre ;
    root-> m_pLeft = root -> m_pRight = NULL ;


    const int * pRootPos = startmid ;
   
    while ( pRootPos <= endmid && * pRootPos!=* startpre ){
        ++ pRootPos ;
    }


    int leftLength  = pRootPos -startmid ;
    if ( pRootPos<= endmid && pRootPos > startmid ){
        root ->m_pLeft = build_BST_core( startpre +1,startpre + leftLength, startmid ,pRootPos -1);
    }
    if ( pRootPos < endmid ){
        root ->m_pRight = build_BST_core( startpre +leftLength +1, endpre, pRootPos +1,endmid );
    }


    return root ;
}




//利用先序和中序构造二叉树
BST_node * build_BST ( int * preorder, int *midorder , const int nSize)
{
    if ( ! preorder || ! midorder || nSize <=0){
        return NULL ;
    }
    return build_BST_core (preorder , preorder+ nSize -1,
                   midorder ,midorder + nSize-1);
}




//中序递归遍历二叉树
void print_preorder_reserve ( BST_node * pRoot )
{
    if ( pRoot ){
        cout <<pRoot -> m_value<< "  " ;
        print_preorder_reserve (pRoot -> m_pLeft);
        print_preorder_reserve (pRoot -> m_pRight);
    }
   
}
//非递归使用栈中序遍历二叉树
void print_preorder_noreserve ( BST_node* pRoot )
{
    if ( pRoot ){
        stack <BST_node *> s;


        do {
            while ( pRoot ){
                cout <<pRoot -> m_value<< " " ;
                s .push ( pRoot);
                pRoot = pRoot -> m_pLeft;
            }
            pRoot = s . top();
            s .pop ();
            pRoot = pRoot -> m_pRight;
        } while ( pRoot || ! s. empty() );
        cout <<endl ;
    } 
}
//非递归不用栈中序遍历二叉树
void print_preorder_nostack ( BST_node * pRoot )
{
    BST_node * prev = NULL ;
    while ( pRoot ){
      
        if ( !pRoot -> m_pLeft ){
            cout <<pRoot -> m_value<< " " ;
            pRoot = pRoot -> m_pRight;
        } else {
            prev = pRoot -> m_pLeft;


            while ( prev -> m_pRight && prev ->m_pRight != pRoot ){
                prev = prev -> m_pRight;
            }
            if ( !prev -> m_pRight ){
                cout <<pRoot -> m_value<< " " ;
                prev ->m_pRight = pRoot;
                pRoot = pRoot -> m_pLeft;
            } else {
                prev ->m_pRight = NULL;
                pRoot = pRoot -> m_pRight;
            }
        }
    }
    cout<< endl ;
}






void print_inorder_reserve ( BST_node * pRoot )
{
    if ( pRoot ){
        print_preorder_reserve (pRoot -> m_pLeft);
        cout <<pRoot -> m_value<< "  " ;
        print_preorder_reserve (pRoot -> m_pRight);
    }
}
void print_inorder_noreserve ( BST_node * pRoot )
{
    if ( pRoot ){
        stack <BST_node *> s;
        do {
            while ( pRoot ){
                s .push ( pRoot);
                pRoot = pRoot -> m_pLeft;
            }
            pRoot = s . top();
            s .pop ();
            cout <<pRoot -> m_value<< " " ;
            
            pRoot = pRoot -> m_pRight;


        } while ( !s . empty() || pRoot );
         cout <<endl ;
    }


}
void print_inorder_nostack ( BST_node * pRoot )
{
    BST_node * prev ;
    while ( pRoot ){
        if ( !pRoot -> m_pLeft ){
            cout <<pRoot -> m_value<< " " ;
            pRoot = pRoot -> m_pRight;
        } else {
            prev = pRoot -> m_pLeft;
            while ( prev -> m_pRight && prev ->m_pRight != pRoot ){
                prev = prev -> m_pRight;
            }
            if ( !prev -> m_pRight ){
                prev ->m_pRight = pRoot;
                pRoot = pRoot -> m_pLeft;
            } else {
                cout <<pRoot -> m_value<< " " ;
                prev ->m_pRight = NULL;
                pRoot = pRoot -> m_pRight;
            }
        }
    }
    cout<< endl ;
}


void print_postorder_reserve ( BST_node * pRoot )
{
    if ( pRoot ){
        print_postorder_reserve (pRoot -> m_pLeft);
        print_postorder_reserve (pRoot -> m_pRight);
        cout <<pRoot -> m_value<< " " ;
    }
}
void print_postorder_noreserve ( BST_node * pRoot )
{
    if ( pRoot ){
        stack <flage_BST_node > s;
        flage_BST_node node ;
        do {
            while ( pRoot ){
                node .flage = false;
                node .p = pRoot;
                s .push ( node);
                pRoot = pRoot -> m_pLeft;
            }
            node = s . top();
            s .pop ();
            if ( node . flage ){
                cout <<node . p-> m_value<< " " ;
            } else {
                node .flage = true;
                s .push ( node);
                pRoot = node . p-> m_pRight;
            }
        } while ( pRoot || ! s. empty() );
        cout <<endl ;
    }
   


}
void print_postorder_nostack_print ( BST_node * pRoot )
{
    if ( pRoot ){
        print_postorder_nostack_print (pRoot -> m_pRight);
        cout <<pRoot -> m_value<< " " ;
    }
}
void print_postorder_nostack ( BST_node* pRoot )
{
    BST_node * prev ;
    BST_node * pRoot_temp = pRoot ;
    while ( pRoot ){
        if ( !pRoot -> m_pLeft ){
            pRoot = pRoot -> m_pRight;
        } else {
            prev = pRoot -> m_pLeft;
            while ( prev -> m_pRight && prev ->m_pRight != pRoot){
                prev = prev -> m_pRight;
            }
            if ( !prev -> m_pRight ){
                prev ->m_pRight = pRoot;
                pRoot = pRoot -> m_pLeft;
            } else {
                prev ->m_pRight = NULL;
                print_postorder_nostack_print (pRoot -> m_pLeft);
                pRoot = pRoot -> m_pRight;
            }
        }
    }
    print_postorder_nostack_print( pRoot_temp );
    cout<< endl ;
}








int main ()
{
    int pre[]={1,2,4,7,3,5,6,8};
    int mid[]={4,7,2,1,5,3,8,6};
    BST_node* pRoot = build_BST ( pre, mid,8);
   // print_preorder_reserve(pRoot);
   // cout<<endl;
   // print_preorder_noreserve(pRoot);
   // print_preorder_nostack(pRoot);


    /* print_inorder_reserve(pRoot);
    cout<<endl;
    print_inorder_noreserve(pRoot);
    print_inorder_nostack(pRoot);*/


    //print_postorder_noreserve(pRoot);
    print_postorder_reserve( pRoot );
    cout<< endl ;
    print_postorder_nostack( pRoot );
   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值