二叉树遍历(非递归)

基于栈的递归消除
递归操作隐式地调用系统栈,使时间和空间性能有比较大的损耗。我们可以根据自己的需要调用合适的栈结构,从而提高效率。
以中序遍历为例:
void InOrderTraverse(BiTree root) {
 InitStack(&s); //初始化栈s
 p=root;
 while( p!=NULL || !IsEmpty(s) ) { //当前访问节点存在或栈不空
  if(p!=NULL) { //当前节点存在
   Push(&s,p); //把当前节点压入栈顶
   p=p->LChild; //继续遍历左子树
  }
  else { //当前节点不存在,回溯
   Pop(&s,&p); //将栈顶赋给p,出栈
   Visit(p->data); //访问节点p
   p=p->RChild; //转而访问右子树
  }
 }
}

二叉树的层序遍历 借助队列结构,先把根节点入队,如果队列不为空,则让队首节点出队,访问该节点并把它的左右孩子分别入队列,然后再出队,再访问,再左右孩子入队,直到队列为空。这样在遍历过程中,是以树的深度为顺序的。
void Traverse(BiTree root) {
 if(root!=null)
  EnQueue(&q,root); //根节点入队
 while(!IsEmpty(q)) {
  BiTree temp = DeQueue(&q); //出队
  Visite(temp);  //访问出队节点
  if(temp->LChild)
   EnQueue(&q,temp->LChild); //出队节点左孩子入队
  if(temp->RChild)
   EnQueue(&q,temp->RChild); //出队节点右孩子入队
 }
}

二叉树的遍历:前序,中序,后序,层序--包括递归和非递归实现
后序遍历还没有明白,继续学习^_^,过几天写个huffman编码的例子来玩玩,不多说了,看代码吧,注意:程序申请的空间并没有释放^_^

  /**/ /* *******************************************************************
     created:    2005/12/30
     created:    30:12:2005   10:39
     filename:     bintree.h
     author:        Liu Qi
    
     purpose:    二叉树的3种遍历方式(包括非递归实现),前序,后序和中序,先访问根节点就是
     前序(部分书籍称为先根遍历,个人觉得该说法更好^_^),类似的,最后访问根节点就是后序
 ******************************************************************** */
 
 
 #ifndef TREE_H
 #define  TREE_H
 
 
 #include  < stdio.h >
 #include  < malloc.h >
 #include  < stack >
 #include  < queue >
 #include  < assert.h >
 
 using   namespace  std;
 
 
 
 typedef  int  ElemType;
 
 typedef  struct  treeT
   {
     ElemType key;
      struct  treeT *  left;
      struct  treeT *  right;
 } treeT,  * pTreeT;
 
 
 
 
  /**/ /* ===========================================================================
 * Function name:    visit
 * Parameter:        root:树根节点指针
 * Precondition:       
 * Description:       
 * Return value:       
 * Author:            Liu Qi, //-
 =========================================================================== */
 static   void  visit(pTreeT root)
   {
      if  (NULL  !=  root)
        {
         printf( "  %d/n " , root -> key);
     }
 }
 
 
 
  /**/ /* ===========================================================================
 * Function name:  BT_MakeNode   
 * Parameter:      target:元素值   
 * Precondition:      None   
 * Postcondition:  NULL != pTreeT
 * Description:      构造一个tree节点,置左右指针为空,并且返回指向新节点的指针   
 * Return value:      指向新节点的指针   
 * Author:            Liu Qi,  [12/30/2005]
 =========================================================================== */
 static  pTreeT BT_MakeNode(ElemType target)
   {
     pTreeT pNode  =  (pTreeT) malloc( sizeof (treeT));
 
     assert( NULL  !=  pNode );
 
     pNode -> key    =  target;
     pNode -> left   =  NULL;
     pNode -> right  =  NULL;
    
      return  pNode;
 }
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_Insert
 * Parameter:        target:要插入的元素值, pNode:指向某一个节点的指针
 * Precondition:         NULL != ppTree
 * Description:        插入target到pNode的后面
 * Return value:        指向新节点的指针
 * Author:            Liu Qi,  [12/29/2005]
 =========================================================================== */
 pTreeT BT_Insert(ElemType target, pTreeT *  ppTree)
   {
     pTreeT Node;
 
     assert( NULL  !=  ppTree );
 
     Node  =   * ppTree;
      if  (NULL  ==  Node)
        {
          return   * ppTree  =  BT_MakeNode(target);
     }
 
      if  (Node -> key  ==  target)     // 不允许出现相同的元素
        {
          return  NULL;
     }
      else   if  (Node -> key  >  target)     // 向左
        {
          return  BT_Insert(target,  & Node -> left);
     }
      else
        {
          return  BT_Insert(target,  & Node -> right);
     }
 }
 
 
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_PreOrder
 * Parameter:        root:树根节点指针
 * Precondition:        None
 * Description:        前序遍历
 * Return value:        void
 * Author:            Liu Qi,  [12/29/2005]
 =========================================================================== */
 void  BT_PreOrder(pTreeT root)
   {
      if  (NULL  !=  root)
        {
         visit(root);
         BT_PreOrder(root -> left);
         BT_PreOrder(root -> right);
     }    
 }
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_PreOrderNoRec
 * Parameter:        root:树根节点指针
 * Precondition:        Node
 * Description:        前序(先根)遍历非递归算法
 * Return value:        void
 * Author:            Liu Qi,  [1/1/2006]
 =========================================================================== */
 void  BT_PreOrderNoRec(pTreeT root)
   {
     stack < treeT  *>  s;
 
      while  ((NULL  !=  root)  ||   ! s.empty())
        {
          if  (NULL  !=  root)
            {
             visit(root);
             s.push(root);
             root  =  root -> left;
         }
          else
            {
             root  =  s.top();
             s.pop();
             root  =  root -> right;
         }
     }
 }
 
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_InOrder
 * Parameter:        root:树根节点指针
 * Precondition:        None
 * Description:        中序遍历
 * Return value:        void
 * Author:            Liu Qi,  [12/30/2005]
 =========================================================================== */
 void  BT_InOrder(pTreeT root)
   {
      if  (NULL  !=  root)
        {
         BT_InOrder(root -> left);
         visit(root);
         BT_InOrder(root -> right);
     }
 }
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_InOrderNoRec
 * Parameter:        root:树根节点指针
 * Precondition:        None
 * Description:        中序遍历,非递归算法
 * Return value:        void
 * Author:            Liu Qi,  [1/1/2006]
 =========================================================================== */
 void  BT_InOrderNoRec(pTreeT root)
   {
     stack < treeT  *>  s;
      while  ((NULL  !=  root)  ||   ! s.empty())
        {
          if  (NULL  !=  root)
            {
             s.push(root);
             root  =  root -> left;
         }
          else
            {
             root  =  s.top();
             visit(root);
             s.pop();
             root  =  root -> right;
         }
     }
 }
 
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_PostOrder
 * Parameter:        root:树根节点指针
 * Precondition:        None
 * Description:        后序遍历
 * Return value:        void
 * Author:            Liu Qi,  [12/30/2005]
 =========================================================================== */
 void  BT_PostOrder(pTreeT root)
   {
      if  (NULL  !=  root)
        {
         BT_PostOrder(root -> left);
         BT_PostOrder(root -> right);
         visit(root);   
     }
 }
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_PostOrderNoRec
 * Parameter:        root:树根节点指针
 * Precondition:        None
 * Description:        后序遍历,非递归算法
 * Return value:        void
 * Author:            Liu Qi, //  [1/1/2006]
 =========================================================================== */
 void  BT_PostOrderNoRec(pTreeT root)
   {
 // 学习中,尚未明白
 }
 
 
  /**/ /* ===========================================================================
 * Function name:    BT_LevelOrder
 * Parameter:        root:树根节点指针
 * Precondition:        NULL != root
 * Description:        层序遍历
 * Return value:        void
 * Author:            Liu Qi,  [1/1/2006]
 =========================================================================== */
 void  BT_LevelOrder(pTreeT root)
   {
     queue < treeT  *>  q;
     treeT  * treePtr;
 
     assert( NULL  !=  root );
 
     q.push(root);
 
      while  ( ! q.empty())
        {
         treePtr  =  q.front();
         q.pop();
         visit(treePtr);
 
          if  (NULL  !=  treePtr -> left)
            {
             q.push(treePtr -> left);   
         }
          if  (NULL  !=  treePtr -> right)
            {
             q.push(treePtr -> right);
         }    
            
     }
 }
 
 
 #endif 
 

测试代码


 #include  < stdio.h >
 #include  < stdlib.h >
 #include  < time.h >
 #include  " tree.h "
 
 #define  MAX_CNT 5
 #define  BASE  100
 
 int  main( int  argc,  char   * argv[])
   {
      int  i;
     pTreeT root  =  NULL;
    
     srand( (unsigned)time( NULL ) );
    
      for  (i = 0 ; i < MAX_CNT; i ++ )
        {
         BT_Insert(rand()  %  BASE,  & root);
     }
 
      // 前序
     printf( " PreOrder:/n " );
     BT_PreOrder(root);
     printf( " /n " );
 
     printf( " PreOrder no recursion:/n " );
     BT_PreOrderNoRec(root);
     printf( " /n " );
    
      // 中序
     printf( " InOrder:/n " );
     BT_InOrder(root);
     printf( " /n " );
 
     printf( " InOrder no recursion:/n " );
     BT_InOrderNoRec(root);
     printf( " /n " );
 
      // 后序
     printf( " PostOrder:/n " );
     BT_PostOrder(root);
     printf( " /n " );
 
      // 层序
     printf( " LevelOrder:/n " );
     BT_LevelOrder(root);
     printf( " /n " );
    
      return   0 ;
 }
如果有兴趣不妨运行一下,看看效果^_^
另外请教怎样让二叉树漂亮的输出,即按照树的形状输出

 

 

 

二叉树是很有用的一种数据结构,遍历则是其基本操作,这里列出实是保证完整性。二叉树后序遍历的非递归遍历中当当前节点存在右子树的时候需要先遍历右子树,因此要对二叉树的节点定义中添加_tag域,标志当前节点右子树是否已经遍历,备用的结构定义和函数:

//二叉树节点定义

class TreeNodeElement

{

       public:

              TreeNodeElement();

 

              TreeNodeElement(int value);

             

              TreeNodeElement(int value,TreeNodeElement* l,TreeNodeElement* r);

 

              ~TreeNodeElement();

 

       private:

       public:

              int _value;

 

              TreeNodeElement* _l;

 

              TreeNodeElement* _r;

 

              bool _tag;

};

 

typedef TreeNodeElement* TreeNode;

//构造函数的定义,前序和中序中相似,只是不学要_tag

TreeNodeElement::TreeNodeElement()

{

       _value = -1;

 

       _l = NULL;

 

       _r = NULL;

 

       _tag = false;

}

 

TreeNodeElement::TreeNodeElement(int value)

{

       _value = value;

 

       _l = NULL;

 

       _r = NULL;

 

       _tag = false;

}

 

TreeNodeElement::TreeNodeElement(int value,TreeNodeElement* l,TreeNodeElement* r)

{

       _value = value;

 

       _l = l;

 

       _r = r;

 

       _tag = false;

}

 

TreeNodeElement::~TreeNodeElement()

{

       delete _l;

              delete _r;

}

//递归实现(visit

void Visit(TreeNode node)

{

       cout<<node->_value<<" ";

}

       二叉树后序遍历的递归和非递归实现:

//递归遍历

void PostRetriveATree(TreeNode root,void (* visit)(TreeNode))

{

       if (root)

       {

              PostRetriveATree(root->_l,visit);

              PostRetriveATree(root->_r,visit);

              (*visit)(root);

       }

}

//非递归遍历,添加#include <stack>

void PostRetriveATreeWithoutRecurve(TreeNode root,void (* visit)(TreeNode))

{

       stack<TreeNode> tree;

 

       while ((root != NULL) || (!tree.empty()))

       {

              while (root != NULL)

              {

                     tree.push(root);

 

                     root = root->_l;

              }

 

              if (!tree.empty())

              {

                     root = tree.top();

 

                     if (root->_tag)  //可以访问

                     {

                            visit(root);

 

                            tree.pop();

                           

                            root = NULL; //第二次访问标志其右子树也已经遍历

                     }

                     else

                     {

                            root->_tag = true;

                            root = root->_r;

                     }

              }

       }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值