首页 > 其他分享 >代码随想录Day12

代码随想录Day12

时间:2024-08-12 20:49:56浏览次数:12  
标签:node 代码 随想录 st vector result Day12 push 节点

二叉树遍历

分为前序、中序、后续、层序四种
其中前中后序属于深度优先搜索,层序属于广度优先搜索

前序遍历顺序:

根节点->左子树->右子树

中序遍历顺序:

左子树->根节点->右子树

后序遍历顺序:

左子树->右子树->根节点
不难发现,前中后其实就是根节点在遍历中的位置
至于层序遍历,顾名思义,就是一层一层的从左到右遍历

递归遍历(前中后)

  1. 确定递归函数的参数和返回值:因为要打印出前序遍历节点的数值,所以参数里需要传入vector来放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,所以递归函数返回类型就是void。
  2. 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了,所以如果当前遍历的这个节点是空,就直接return。
  3. 确定单层递归的逻辑:前序遍历是中左右的顺序,所以在单层递归的逻辑,是要先取中节点的数值。

上代码(●'◡'●)

前序:
class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};
中序:
class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        traversal(cur->left, vec);  // 左
        vec.push_back(cur->val);    // 中
        traversal(cur->right, vec); // 右
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};
后序:
class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
        vec.push_back(cur->val);    // 中
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

迭代遍历(前中后)

递归的底层实现其实就是栈
所以我们可以用栈来实现二叉树的前中后序遍历
但是由于会比较麻烦,三种遍历没法统一,所以我们来看另一种方法:
使用栈的话,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
迭代
可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。

上代码(●'◡'●)

前序:
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                st.push(node);                          // 中
                st.push(NULL);
            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};
中序:
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)

                st.push(node);                          // 添加中节点
                st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。

                if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)
            } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.top();    // 重新取出栈中元素
                st.pop();
                result.push_back(node->val); // 加入到结果集
            }
        }
        return result;
    }
};
后序:
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);                          // 中
                st.push(NULL);

                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左

            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

统一的代码模式,看着确实舒服 d=====( ̄▽ ̄*)b

层序遍历

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和之前的都不太一样。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
层序遍历

上代码(●'◡'●)

迭代:
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            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;
    }
};
递归:
class Solution {
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth)
    {
        if (cur == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};

写博不易,请大佬点赞支持一下8~

标签:node,代码,随想录,st,vector,result,Day12,push,节点
From: https://www.cnblogs.com/Murder-sans/p/18355719/dmsxl_Day12

相关文章

  • BlackMarket靶机复现【附代码】(权限提升)
    TheBlackmarket/BlackMarket靶机下载地址:https://www.vulnhub.com/entry/blackmarket-1,223/https://www.vulnhub.com/entry/blackmarket-1,223/1.主机发现+端口扫描+目录扫描+敏感信息获取1.1.主机发现nmap-sn192.168.7.0/24|grep-B2'08:00:27:D6:0A:18'1.2.......
  • 巧用Array.forEach:简化循环与增强代码可读性;Array.forEach怎么用;面对大量数据时怎么提
    目录Vue.js中的Array.forEach:简化循环与增强代码可读性一、引言二、Array.forEach()的使用与技巧1、基本语法2、返回值3、使用Array.forEach()的优势4、Array.forEachvsfor循环5、Array.forEach()使用技巧三、Array.forEach()的应用情景1、复杂数据处理2、实时更......
  • 「代码随想录算法训练营」第三十五天 | 动态规划 part8
    121.买卖股票的最佳时机题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/文章讲解:https://programmercarl.com/0121.买卖股票的最佳时机.html题目难度:简单视频讲解:https://www.bilibili.com/video/BV1Xe4y1u77q题目状态:有一半的思路思路一:贪心对......
  • PHP性能优化秘籍:让代码飞起来
    标题:PHP性能优化秘籍:让代码飞起来PHP作为一门广泛使用的服务器端脚本语言,其性能直接影响到Web应用的响应速度和用户体验。本文将深入探讨PHP性能优化的多种技巧,从代码层面到服务器配置,帮助你的PHP应用达到最佳性能。我们将通过一系列详细的优化策略和实际代码示例,展示如何......
  • 代码质量的守护者:Python静态代码分析工具的集成之道
    标题:代码质量的守护者:Python静态代码分析工具的集成之道在软件开发过程中,代码质量是至关重要的一环。Python作为一种流行的编程语言,拥有众多的静态代码分析工具,它们能够在代码运行之前检测潜在的错误和代码风格问题。本文将深入探讨如何将这些工具集成到Python开发流程中,从......
  • 腾讯云AI代码助手 —— 编程新体验,智能编码新纪元
    阅读导航引言一、开发环境介绍1.支持的编程语言2.支持的集成开发环境(IDE)二、腾讯云AI代码助手使用实例1.开发环境配置2.代码补全功能使用......
  • 在clion IDE中编写ADI CCES的工程代码,cmake设置
    有时需要在CCES中编译代码,或者在stm32的mdk或者stm32cubeide中编译,但是习惯了在clion中编写代码,但是clion中需要CMAKES设置,所以需要自己写一个cmake文件,下面是一个模板文件cmake_minimum_required(VERSION3.24)project(proj_name)#add_definitions(-DCORE0-D_DEBUG-DAD......
  • 音视频低代码 UI 组件开发方案 3步集成,最快1天上线应用
    腾讯音视频低代码UI组件开发方案3步集成,最快1天上线应用链接:https://curl.qcloud.com/XbimkuR5腾讯音视频低代码UI组件开发方案TUIKit提供了一种高效、低门槛的方式来快速实现全球跨平台、超高品质的实时音视频互动场景。以下是关于该方案的3步集成流程,以及为何它能实现最......
  • SpringSecurity+前端项目+redis完成认证授权的代码
    1.前端准备工作--都在全局main.js页面中设置的1.1.创建Vue工程后,并导入elementui和axios,添加连接后端项目的路径,把axios挂载到Vue1.2.前置路由守卫(所有路由跳转前核实一下身份)//前置路由守卫--所有的路由跳转都先经过这里//to:即将要访问的路径from:从哪里来......
  • 二分图判定 代码源初级
    //1001二分图判定.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>#include<memory.h>usingnamespacestd;/*http://oj.daimayuan.top/course/14/problem/797给你一张简单无向图,你需要判断这张图是否为二分图。图用以下形式给......