前序、中序、后序遍历二叉树递归与非递归实现

前序、中序、后序递归

非常简单,调整访问根节点的时机即可

void traverse(TreeNode* root){
      if(!root) return;            //递归出口
      //cout << root->val <<endl;  //前序
      traverse(root->left);
      //cout << root->val <<endl;  //中序
      traverse(root->right);
      //cout << root->val <<endl;  //后序
}

前序非递归

利用栈,注意先放入右孩子,再放入左孩子

void traverse(TreeNode* root){
      if(!root) return;
      stack<TreeNode*> s;
      s.push(root);
      while(!s.empty()){
            TreeNode* curr=s.top();
            s.pop();
            cout << curr->val << endl;
            if(curr->right) s.push(curr->right);
            if(curr->left) s.push(curr->left);
      }
}

中序非递归

利用栈,每一个结点都要先压入所有左孩子

  • 使用curr=curr->right,是因为中序遍历先访问根节点再访问右孩子结点
  • 如果curr->right==NULL,再回到循环开始,不会进入第二层循环,相当于上一次访问的根节点是这个访问结点的左孩子
void traverse(TreeNode* root){
      stack<TreeNode*> s;
      TreeNode* curr=root;
      while(curr||!s.empty()){
            while(curr){
                  s.push(curr);
                  curr=curr->left;
            }
            curr=s.top();
            s.pop();
            cout << curr->val << endl;
            curr=curr->right;      
      }
}

后序非递归

和中序类似,利用栈,每一个结点都要先压入所有左孩子
在访问根节点之前,要判断是右孩子是否存在或上一个访问的结点是不是右孩子

  • 如果右孩子存在并且上一个访问的不是右孩子,那么重新将根节点压入,右孩子结点进入循环
  • 其他情况,都可以直接访问根节点
void traverse(TreeNode* root){
        stack<TreeNode*> s;
        TreeNode* pre=root,*curr=root;
        while(curr||!s.empty()){
            while(curr){
                s.push(curr);
                curr=curr->left;
            }
            curr=s.top();
            s.pop();
            if(curr->right&&pre!=curr->right){
                s.push(curr);
                curr=curr->right;
            } 
            else {
                cout << curr->val << endl;
                pre=curr;//更新指针pre
                curr=NULL;//访问完根节点,下一个要访问的结点从栈中取出。不取空值,又会继续找左孩子
            }
        }
        return ans;
}
posted @ 2020-10-07 11:27  肥斯大只仔  阅读(88)  评论(0编辑  收藏  举报