二叉树的非递归(迭代)遍历

目录

结构

前序遍历

中序遍历

后序遍历

结构

使用递归的方式时,将一个结点分为左子树,右子树,根。

我们使用非递归时,将树分为左路结点和右子树,同时在定义一个栈。先将左结点全放入栈中,根据栈的特性(后入先出),像递归一样从下先上遍历树。

前序遍历

当我们用前序非递归访问一棵树时,分为两步

1、左路节点:访问+入栈。

 

2、这些左路节点的右子树。

   右子树通过迭代的方式再分成左路节点和左路节点的右子树的方式访问。也就是意味着当数据

   出栈时,当前节点的左树就访问完了,当栈为空时,就结束。

vector<int> preorderTraversal(TreeNode* root) 
{
 vector<int> ret;   //定义一个数组
 stack<TreeNode*> st;   //定义一个栈
 TreeNode* cur=root;   
       
 while(cur || !st.empty())  
 {
     //
     while(cur) //访问左路结点并且入栈
     {
          ret.push_back(cur->val);  //尾插数据
          st.push(cur);       //入栈
          cur=cur->left;    
     }

     TreeNode* top=st.top();  //找到最左边的数据
     st.pop();    //出栈
 
     cur=top->right;  //迭代遍历右子树
            
     }

    return ret;  
 }
};

中序遍历

使用递归的思路时,将一个结点分为左子树,右子树,根,中序遍历就是  “根,左子树,右子树”

和前序类似,不过在左路节点入栈是,不访问数据

1、左路节点 (入栈)
2、取栈中的节点,(访问节点+访问节点的右子树)

代码的实现:

 vector<int> inorderTraversal(TreeNode* root) 
{
  vector<int> vi;
  stack<TreeNode*> st;
  TreeNode* cur=root;
        
  //循环迭代开始,cur指向节点,就是开始访问这棵树
  while(cur || !st.empty())
  {
     //左路节点入栈
     while (cur)
     {
       st.push(cur);
       cur=cur->left;
     } 
 
      //取出栈中节点,访问和节点的右子树
      TreeNode* top=st.top();

      st.pop();
      vi.push_back(top->val);
      cur=top->right;
   }

   return vi; 
}

后序遍历

使用递归的思路时,将一个结点分为左子树,右子树,根,后序遍历就是  “左子树,右子树,根”

非递归时:只有不仅要先访问过当前结点的左结点还需要访问当前结点的右结点,最后才访问结点的数据,因此需要多定义一种指针(listnode)指向上一个访问的结点,当需要访问的结点的右节点等于listnode时,表示当前结点的右结点已经访问过了,便可以访问当前结点的数据。

和前面一样,分两步 

1.左路结点入栈
 2.在访问左路节点地右子树

代码实现:

vector<int> postorderTraversal(TreeNode* root) 
{
  vector<int> vi;
  stack<TreeNode*> st;
  TreeNode* lastNode = NULL; //最近访问的结点
  TreeNode* cur= root;

  while(cur || !st.empty())
  {
      while(cur)  // //1.左路结点入栈
      {
           st.push(cur);
          cur=cur->left;
      }
       //取到左路节点
      TreeNode* top=st.top();
      //如果左路节点的右为空或者上一个最近访问结点是右子树的跟,则表示右子树已经访问过了,可以 
        访问这个结点了,否则迭代器访问右子树
      if(top->right==NULL || lastNode==top->right)  //访问当前结点
      {
         vi.push_back(top->val);
         lastNode=top;
         st.pop();
      }
      //迭代器访问右子树
      else
      {
          cur=top->right;
      }
}
      return vi;
}

我们发现非递归遍历一棵树时,大致都是相似的,不同点在于当我们访问当前结点的时机不同

本篇就分享到这里如果本文对您有帮助请点赞支持一下~

文章尚有不足,欢迎大牛指正.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值