二叉树遍历(先序、中序、后序) 递归和非递归 c++

参考https://www.jianshu.com/p/456af5480cee

一、代码

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

//可参考 https://www.jianshu.com/p/456af5480cee
//二叉树遍历(先序、中序、后序) 递归和非递归

struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x),left(NULL),right(NULL){}
};

//先序遍历 递归
void preVisit1(TreeNode* root){
    if(!root){
        return;
    }
    cout << root->val << " ";
    preVisit1(root->left);
    preVisit1(root->right);
}
//先序遍历 非递归
void preVisit2(TreeNode* root){
    stack<TreeNode*> s;
    vector<int> vec;
    TreeNode* node = root;
    while(node || !s.empty()){
        while(node){
            s.push(node);
            vec.push_back(node->val);
            node = node->left;
        }//退出条件为node空(左子节点遍历到头了),然后弹栈往右边找一个节点
        if(!s.empty()){
            node = s.top();
            s.pop();
            node = node->right;
        }
    }
    for(int i=0;i<vec.size();i++){
        cout << vec[i] << " ";
    }
}

//中序遍历  递归
void midVisit1(TreeNode* root){
    if(!root){
        return;
    }
    midVisit1(root->left);
    cout << root->val << " ";
    midVisit1(root->right);
}

//中序遍历  非递归
void midVisit2(TreeNode* root){
    //和先序遍历非递归非常相似
    TreeNode* node = root;
    stack<TreeNode*> s;
    vector<int> vec;
    while(node || !s.empty()){
        while(node){
            s.push(node);
            node = node->left;
        }
        if(!s.empty()){
            node = s.top();
            s.pop();
            vec.push_back(node->val);
            node = node->right;
        }
    }
    for(int i=0;i<vec.size();i++){
        cout << vec[i] << " ";
    }
}

//后序遍历  递归
void postVisit1(TreeNode* root){
    if(!root){
        return;
    }
    postVisit1(root->left);
    postVisit1(root->right);
    cout << root->val << " ";
}

//后序遍历  非递归1
//后序:左右根 ->逆序后变为:根右左 ->和先序遍历(根左右)非常相似
void postVisit2(TreeNode* root){
    TreeNode* node = root;
    stack<TreeNode*> s;
    vector<int> vec;
    while(node || !s.empty()){
        while(node){
            s.push(node);
            vec.push_back(node->val);
            node = node->right;
        }
        if(!s.empty()){
            node = s.top();
            s.pop();
            node = node->left;
        }
    }
    //将vec逆序输出
    reverse(vec.begin(), vec.end());
    for(int i=0;i<vec.size();i++){
        cout << vec[i] << " ";
    }
}

//后序遍历  非递归2
void postVisit3(TreeNode* root){
    TreeNode* node = root;
    TreeNode* last_visit = NULL;
    stack<TreeNode*> s;
    vector<int> vec;
    while(node || !s.empty()){
        while(node){
            s.push(node);
            node = node->left;
        }
        node = s.top();
        if(!node->right || node->right==last_visit){//如果右节点为空,或则右子树已经访问完
            vec.push_back(node->val);
            s.pop();  //访问节点后才pop
            last_visit = node;
            node = NULL;
        }else{
            node = node->right;
        }
    }
    for(int i=0;i<vec.size();i++){
        cout << vec[i] << " ";
    }
}

int main(){

    //构建一个二叉树
    TreeNode* a = new TreeNode(1);
    TreeNode* b = new TreeNode(2);
    TreeNode* c = new TreeNode(3);
    TreeNode* d = new TreeNode(4);
    TreeNode* e = new TreeNode(5);
    TreeNode* f = new TreeNode(6);
    TreeNode* g = new TreeNode(7);
    TreeNode* h = new TreeNode(8);
    a->left = b;
    a->right = c;
    b->left = d;
    d->right = f;
    f->left = g;
    f->right = h;
    c->right = e;

    cout << "preVisit1: ";
    preVisit1(a);
    cout << "\npreVisit2: ";
    preVisit2(a);

    cout << "\n\nmidVisit1: ";
    midVisit1(a);
    cout << "\nmidVisit2: ";
    midVisit2(a);

    cout << "\n\npostVisit1: ";
    postVisit1(a);
    cout << "\npostVisit2: ";
    postVisit2(a);
    cout << "\npostVisit3: ";
    postVisit3(a);

}

二、图解 -(非递归)栈中元素变化

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值