遍历二叉树的迭代和递归方法

二叉树的问题,一定要明白到底应该深度优先(前中后序)还是广度优先(层序遍历)

最基本的遍历方式:深度优先和广度优先

深度优先:前、中、后序(递归法和迭代法均可)

广度优先:层次遍历(迭代法)

栈其实就是递归的一种实现结构,也就是说前中后序遍历的逻辑其实都是可以借助栈使用非递归的方式来实现的;

广度优先遍历(层序遍历)的实现一般使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。

二叉树节点的定义框架:

复制代码
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
复制代码
二叉树的递归遍历框架:

复制代码
/二叉树的遍历框架/
void traverse(TreeNode root)
{
//前序遍历:先访问根节点,再前序访问左子树,再访问右子树
traverse(root->left);
//中序遍历:先中序访问左子树,再访问根节点,再访问右子树
traverse(root->right);
//后续遍历:先后续访问左子树,再访问右子树,再访问根节点
}
复制代码
一、二叉树的前序遍历:迭代和递归

复制代码
class Solution {
public:
//vector result;//递归的话定义在这里
vector preorderTraversal(TreeNode* root) {
//递归方式
/*
if(root == nullptr)
return {};
result.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
return result;
/
//当然可以使用迭代解法,因为递归本身就是用栈来实现的,可以通过栈来迭代操作
//但是要注意栈的特性是后入先出,前序的话,就是先放入根节点赋值操作弹出,再放入右节点、左节点,再弹出,这样左节点就会先出,先赋值操作,就是前序了
stack<TreeNode
> sta;
vector result;
sta.push(root);
while(!sta.empty()) {
int size = sta.size();
for(int i=0; i<size; i++) {
TreeNode* node = sta.top();
sta.pop();
result.push_back(node->val);
if(node->right)
sta.push(node->right);
if(node->left)
sta.push(node->left);
}
}
return result;
}
};
复制代码
二、二叉树的后序遍历:迭代和递归

复制代码
/**

  • Definition for a binary tree node.
  • struct TreeNode {
  • int val;
    
  • TreeNode *left;
    
  • TreeNode *right;
    
  • TreeNode() : val(0), left(nullptr), right(nullptr) {}
    
  • TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    
  • TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
    
  • };
    /
    class Solution {
    public:
    //vector result;//递归解法定义在这里
    vector postorderTraversal(TreeNode
    root) {
    /*
    if(root == nullptr)
    return {};
    postorderTraversal(root->left);
    postorderTraversal(root->right);
    result.push_back(root->val);
    return result;
    /
    //本题还可以采用迭代解法,因为递归就是用栈来实现的
    //考虑实现的过程
    //后序遍历是左右中的顺序,但是我们在迭代的时候肯定会先访问根节点,也就是中间的节点,所以考虑先访问和处理中间节点,再处理右节点,再处理左边节点,最后将结果翻转就行了
    stack<TreeNode
    > sta;
    vector result;
    sta.push(root);
    while(!sta.empty()) {
    int size = sta.size();
    for(int i=0; i<size; i++) {
    TreeNode* node = sta.top();
    sta.pop();
    result.push_back(node->val);
    if(node->left)
    sta.push(node->left);
    if(node->right)
    sta.push(node->right);
    }
    }
    reverse(result.begin(), result.end());
    return result;
    }
    };
    复制代码
    三、二叉树的中序遍历:迭代和递归

复制代码
/**

  • Definition for a binary tree node.
  • struct TreeNode {
  • int val;
    
  • TreeNode *left;
    
  • TreeNode *right;
    
  • TreeNode() : val(0), left(nullptr), right(nullptr) {}
    
  • TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    
  • TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
    
  • };
    /
    class Solution {
    public:
    //vectorresult;//递归写法这里定义
    vector inorderTraversal(TreeNode
    root) {
    /递归解法
    if(root == nullptr)
    return {};
    inorderTraversal(root->left);
    result.push_back(root->val);
    inorderTraversal(root->right);
    return result;
    /
    //还能采用迭代解法,用栈来解决,因为递归本身就是用栈来实现的,因此是完全行得通的
    //中序的顺序是左中右,那出栈的时候,处理的顺序肯定是右中左
    //搞清楚访问和处理的概念
    //访问:将节点入栈
    //处理:将节点的值放入结果集
    //中序的访问和处理的顺序是不一样的,所以要借助指针进行访问,也就是将节点放入栈中,用栈来做处理,也就是放入结果集
    vector result;
    stack<TreeNode
    > sta;
    TreeNode
    cur = root;
    while(cur != nullptr || !sta.empty()) {
    if(cur != nullptr) {//指针用来访问节点,访问到左边最底层的时候,指针和要开始处理的位置就一样了
    sta.push(cur);//将访问的节点放进栈
    cur = cur->left;//最左的子节点最后放进去,所以会先出栈 左
    }
    else {
    cur = sta.top();
    sta.pop();
    result.push_back(cur->val); //中
    cur = cur->right; //右
    }
    }
    }
    };
    复制代码
    四、二叉树的层序遍历:迭代和递归

复制代码
/**

  • Definition for a binary tree node.
  • struct TreeNode {
  • int val;
    
  • TreeNode *left;
    
  • TreeNode *right;
    
  • TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    
  • };
    /
    class Solution {
    public:
    vector<vector> levelOrder(TreeNode
    root) {
    queue<TreeNode*> que;//创建一个队列,层序遍历树的需要用队列来实现,队列中是二叉树的节点
    if(root != nullptr)
    que.push(root);//如果头结点不为空的话,先将头结点放到队列中,因为头结点也就是第一行,只有这一个元素,所以直接放进去
    vector<vector> result;//定义返回值,返回的是一个二维数组
    while(!que.empty()) {
    int size = que.size();//同一行可能不止一个元素,要循环都进行遍历,又因为下面要进行pop操作,que.size()是一个变化的值,所以这里存储数量
    vector vec;//用于临时存储每一行的节点值,最后统一存入返回的二维数组中
    for(int i=0; i<size; i++) {
    TreeNode* node = que.front();
    que.pop();//
    vec.push_back(node->val);
    if(node->left)
    que.push(node->left);//将这个节点的左右子节点放入队列中
    if(node->right)
    que.push(node->right);
    }
    result.push_back(vec);
    }
    return result;
    }
    };
    深圳网站建设www.sz886.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值