二叉树的深度遍历

news2024/12/23 9:45:18

目录

深度优先遍历:

二叉树节点定义: 

递归法:

前序

中序 

后序

迭代法:

前序

中序

后序

迭代法(统一写法)

前序

中序

后序

广度优先遍历:


二叉树的遍历方法包括两种:深度优先遍历广度优先遍历

下面分别介绍这两种遍历方法的具体实现。

代码随想录 (programmercarl.com)icon-default.png?t=N7T8https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E7%A7%8D%E7%B1%BB


深度优先遍历:

        即先往深走,遇到叶子节点再往回走。又包括前序、中序、后序遍历,可分别由递归法与迭代法实现。(PS:这里的三种顺序指的是中间节点的遍历顺序)

前序遍历:中左右

中序遍历:左中右

后序遍历:左右中

二叉树节点定义:
 

// 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:
    void traversal(TreeNode* cur, vector<int>& vec){
        if(cur == nullptr) return;
        vec.push_back(cur->val);
        traversal(cur->left, vec);
        traversal(cur->right, vec);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> preVec;
        if(root==nullptr) return preVec;
        traversal(root, preVec);
        return preVec;
    }
};

中序 

 // 递归法
class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec){
        if(cur == nullptr) return;
        traversal(cur->left, vec);
        vec.push_back(cur->val);
        traversal(cur->right, vec);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> mid_vec;
        if(root == nullptr) return mid_vec;
        traversal(root, mid_vec);
        return mid_vec;
    }
};

后序

 // 递归法
class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec){
        if(cur == nullptr) return;
        traversal(cur->left, vec);
        traversal(cur->right, vec);
        vec.push_back(cur->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> post_vec;
        if(root == nullptr) return post_vec;
        traversal(root, post_vec);
        return post_vec;
    }
};

迭代法:

前序

 // 迭代法
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> preVec;
        stack<TreeNode*> preStack;
        if(root==nullptr) return preVec;

        preStack.push(root);
        while(!preStack.empty()){
            TreeNode* cur = preStack.top();
            preStack.pop();
            preVec.push_back(cur->val);     // 前序
            // 中节点的右左入栈,左右出栈
            if(cur->right) preStack.push(cur->right);
            if(cur->left) preStack.push(cur->left);
        }
        return preVec;
    }
};

中序

 // 迭代法
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> mid_vec;
        stack<TreeNode*> mid_stack;
        if(root == nullptr) return mid_vec;
        
        TreeNode* cur = root;
        while(cur || !mid_stack.empty()){
            if(cur){
                mid_stack.push(cur);
                cur = cur->left;
            }
            else{
                cur = mid_stack.top();
                mid_stack.pop();
                mid_vec.push_back(cur->val);    // 中序
                cur = cur->right;
            }
        }

        return mid_vec;
    }
};

后序

 // 迭代法
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> post_vec;
        stack<TreeNode*> post_stack;
        if(root == nullptr) return post_vec;
        post_stack.push(root);

        while(!post_stack.empty()){
            TreeNode* cur = post_stack.top();
            post_stack.pop();
            post_vec.push_back(cur->val);    //前序(后面逆转)
            //左右入栈,右左出栈
            if(cur->left) post_stack.push(cur->left);
            if(cur->right) post_stack.push(cur->right);
        }
        // 中右左->左右中
        reverse(post_vec.begin(),post_vec.end());
        return post_vec;
    }
};

迭代法(统一写法)

前序

 // 迭代法(统一风格)
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> preVec;
        stack<TreeNode*> preStack;
        if(root) preStack.push(root);

        while(!preStack.empty()){
            TreeNode* cur = preStack.top();
            if(cur){    // 入栈标记处理节点
                preStack.pop();
                if(cur->right) preStack.push(cur->right);   //右入栈
                if(cur->left) preStack.push(cur->left);     //左入栈
                preStack.push(cur);                        //中入栈
                preStack.push(nullptr);                    //push空节点,标记处理节点
            }
            else{   // 遇空节点出栈处理
                preStack.pop();
                preVec.push_back(preStack.top()->val);
                preStack.pop();
            }
        }
        return preVec;
    }
};

中序

 // 迭代法
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> mid_vec;
        stack<TreeNode*> mid_stack;
        if(root) mid_stack.push(root);
        
        while(!mid_stack.empty()){
            TreeNode* cur = mid_stack.top();
            if(cur){    // 入栈标记处理节点
                mid_stack.pop();
                if(cur->right) mid_stack.push(cur->right);
                mid_stack.push(cur);
                mid_stack.push(nullptr);
                if(cur->left) mid_stack.push(cur->left);
            }
            else{       // 遇空节点出栈处理
                mid_stack.pop();
                mid_vec.push_back(mid_stack.top()->val);    // 中序
                mid_stack.pop();
            }
        }
        return mid_vec;
    }
};

后序

 // 迭代法(统一风格)
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> post_vec;
        stack<TreeNode*> post_stack;
        if(root) post_stack.push(root);

        while(!post_stack.empty()){
            TreeNode* cur = post_stack.top();
            if(cur){    // 入栈标记处理节点
                post_stack.push(nullptr);                       // 中
                if(cur->right) post_stack.push(cur->right);     // 右
                if(cur->left) post_stack.push(cur->left);       // 左
            }
            else{       // 遇空节点出栈处理
                post_stack.pop();
                post_vec.push_back(post_stack.top()->val);
                post_stack.pop();
            }

        }
        return post_vec;
    }
};

广度优先遍历:

        一层一层的去遍历。
        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue创建项目配置情况

刚开始接触vue项目创建和运行因为node版本和插件版本不一致时长遇到刚装好插件&#xff0c;项目就跑不起来的情况&#xff0c;特此记录一下 vue -V vue/cli 5.0.8 node -v v12.22.12 npm -v 6.14.16 关闭驼峰命名检查、未使用语法检查 package.json文件内容&#xff1a; {&…

3dmax渲染出现马赛克该怎么办?

为什么渲染会出现马赛克问题呢&#xff0c;什么原因导致的呢&#xff0c;该如何解决呢&#xff1f; 原因一 3dmax渲染出来马赛克可能是因为勾选了 dont reder final image(不渲染最终图像)&#xff0c;所以导致3dmax渲染出来马赛克。 解决方法&#xff1a; 打开渲染器设置菜…

web练习2

需求 1.计算用户指定的数值内的奇数和。例如用户输入的是10则计算13579的和 <!doctype html> <html lang"en"> <head><meta charset"utf-8"><title>作业1</title></head> <body> <script>//计算用…

迅软科技丨IT企业如何应对数据泄密危机?

随着信息技术的快速发展&#xff0c;软件IT行业面临着前所未有的数据安全挑战。黑客攻击、病毒传播、内部泄密等安全威胁层出不穷&#xff0c;给企业的核心资产和运营带来严重威胁。同时&#xff0c;国家对于数据安全的法律法规也日益严格&#xff0c;要求企业必须采取更加有效…

边缘计算的挑战和机遇(结合RDH-EI)

边缘计算的挑战和机遇 边缘计算面临着数据安全与隐私保护、网络稳定性等挑战&#xff0c;但同时也带来了更强的实时性和本地处理能力&#xff0c;为企业降低了成本和压力&#xff0c;提高了数据处理效率。因此&#xff0c;边缘计算既带来了挑战也带来了机遇&#xff0c;需要我…

瑞_Java开发手册_(七)设计规约

文章目录 设计规约的意义设计规约 &#x1f64a;前言&#xff1a;本文章为瑞_系列专栏之《Java开发手册》的设计规约篇。由于博主是从阿里的《Java开发手册》学习到Java的编程规约&#xff0c;所以本系列专栏主要以这本书进行讲解和拓展&#xff0c;有需要的小伙伴可以点击链接…

K8S中使用helm安装MinIO

注意事项 使用helm部署MinIO分为两部分 helm部署MinIO operator&#xff0c;用来管理tenant&#xff08;K8S集群中只能部署一个&#xff09;helm部署MinIO tenant&#xff0c;真实的MinIO Cluster&#xff08;K8S集群中可以部署多个&#xff09; 使用helm部署到K8S集群&…

CC工具箱使用指南:【获取所有字段信息】

一、简介 这个工具的目的简单易懂&#xff0c;就是获取选定要素图层的所有字段信息。 本身不对要素图层作任何处理&#xff0c;只是一个查看属性的工具。 问我要用在什么地方&#xff0c;我也不知道-_- 二、工具参数介绍 点击【信息获取】组里的【获取所有字段信息】工具&a…

vue3二次封装element-ui中的table组件

为什么要做这件事 借助封装table组件的过程来巩固一下vue3相关知识点。 组件有哪些配置项 options:表格的配置项data: 表格数据源elementLoadingText&#xff1a;加载文案elementLoadingSpinner&#xff1a;加载图标elementLoadingBackground&#xff1a;背景遮罩的颜色elem…

解码Java SPI:深入理解与实践【七】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 解码Java SPI&#xff1a;深入理解与实践【七】 前言SPI机制简介&#xff1a;SPI的工作原理java标准SPI示例总结 前言 在编写Java应用程序时&#xff0c;我们经常需要使用不同的库和框架来扩展功能。…

NET Core发布 HTTP Error 500.31 - Failed to load ASP.NET Core runtime

记录一下踩过的坑&#xff1a; 首先&#xff0c;不论是500.31还是500.30 &#xff0c;首先确保安装了三个文件 1.NET Core RunTime 2.NET SDK 3.NET Hosting 其次&#xff0c;确保三个文件的版本一致&#xff0c;如下&#xff1a; 要装就统一装同一个大版本&#xff0c;不要东…

streamlit配合plotly绘制交互式图表

借助st.plotly_chart实现 官方介绍&#xff1a;st.plotly_chart 案例&#xff1a; import pandas as pd import plotly.graph_objs as go import plotly.express as pxst.subheader("课题组成员", dividerred) df pd.read_excel("./data/summary.xlsx"…

护眼灯到底有用吗知乎?护眼台灯的作用

近年来&#xff0c;随着电子产品的普及和使用时间的增加&#xff0c;人们对眼部健康的关注度也日益提高。为解决由此带来的问题&#xff0c;护眼台灯在这一背景下崭露头角。护眼台灯是一种融合先进技术的台灯&#xff0c;旨在缓解眼部疲劳并保护视力&#xff0c;那护眼台灯究竟…

第七站:C++面向对象训练

1:介绍 创建两个类,一个boy类,一个girl类,实现对两个类的数据输入,并通过main函数,对两个类的成员进行比较匹配 涉及: vector容器,面向对象,const关键字, stringstream(sstream.h) stringstream用法 stringstream ret;//可以将写入的数据转换成字符串 ret << &quo…

利用python将Excel文件拆分为多个CSV

目录 一、准备工作 二、拆分Excel文件为多个CSV 1、读取Excel文件&#xff1a; 2、确定要拆分的列&#xff1a; 3、创建空的字典来存储CSV文件&#xff1a; 4、循环遍历数据并根据类别拆分&#xff1a; 5、打印或返回CSV文件名字典&#xff1a; 6、保存CSV到特定目录&a…

python.24.1.16函数

python自带函数 自定义函数 参数的使用

机器学习——支持向量机SVM

1 摘要&#xff1a; 支持向量机&#xff08;SVM&#xff09;是一种二类分类模型&#xff0c;其基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大&#xff0c;间隔最大使它有别于感知机&#xff0c;支持向量机也可通过核技巧使它成为非线性分类器。支持…

presto 支持regexp_count

一、背景 1、查询regexp_count 函数提示未注册 用户想正则查询特定字符出现次数 function regexp_count not registered 二、调研 1、官网地址&#xff1a; Presto Documentation — Presto 0.284 Documentation 2、regexp_extract_all Regular Expression Functions —…

c++时间复杂度详解

1.基本概念 在计算机科学中&#xff0c;时间复杂性&#xff0c;又称时间复杂度&#xff0c;算法的时间复杂度是一个函数&#xff0c;它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述&#xff0c;不包括这个函数的低阶项和…

【Mybatis系列】Mybatis空值关联

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…