【二叉树】1-5,理论基础、前中后序遍历的递归法和迭代法、层序遍历

news2024/11/27 9:33:20

理论基础、前中后序遍历的递归法和迭代法、层序遍历

  • 1,二叉树的种类
    • 满二叉树
    • 完全二叉树
    • 二叉搜索树
    • 平衡二叉搜索树
  • 2,存储方式
    • 链式存储
    • 线式存储
  • 3,二叉树的遍历
    • 深度优先搜索
      • 前序遍历(递归法、迭代法)
      • 中序遍历(递归法、迭代法)
      • 后序遍历(递归法、迭代法)
    • 广度优先搜索
      • 层次遍历(迭代法、递归法)
  • 4,二叉树的定义

1,二叉树的种类

满二叉树

除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。
请添加图片描述

完全二叉树

一个深度为k的有n个节点的二叉树,对树中的节点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
请添加图片描述

二叉搜索树

二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree)。

二叉搜索树是具有有以下性质的二叉树:

若左子树不为空,则左子树上所有节点的值均小于或等于它的根节点的值。
若右子树不为空,则右子树上所有节点的值均大于或等于它的根节点的值。
左、右子树也分别为二叉搜索树。
请添加图片描述

平衡二叉搜索树

平衡二叉搜索树的任何结点的左子树和右子树高度最多相差1。,并且左右两个子树都是一棵平衡二叉树。
请添加图片描述

容器map、set、multimap、multiset的底层原理都是平衡二叉搜索树
所以map中key和set中的元素都是有序的

unordered map和unordered set的底层原理为哈希表

2,存储方式

分为链式存储和线式存储

链式存储

链式存储方式就用指针
请添加图片描述

线式存储

(用的少了解即可)

顺序存储的方式就是用数组。
请添加图片描述

线式存储时,有一点i,他的左孩子下标为2i+1,他的右孩子下标为2i+2

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:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 中
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return result;
    }
};

中序遍历(递归法、迭代法)

左中右
递归法:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    vec.push_back(cur->val);    // 中
    traversal(cur->right, vec); // 右
}

迭代法:
访问顺序和处理顺序不同,所以代码和前后续遍历不同

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;                // 左
            } else {
                cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);     // 中
                cur = cur->right;               // 右
            }
        }
        return result;
    }
};

后序遍历(递归法、迭代法)

左右中
递归法:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    traversal(cur->right, vec); // 右
    vec.push_back(cur->val);    // 中
}

迭代法:
访问顺序和处理顺序相同

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
    }
};

广度优先搜索

层次遍历(迭代法、递归法)

借助一个队列,保存每一层的节点

队列记录当前层的元素个数,弹出时按队列里储存的个数弹出

迭代法:

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;
    }
};

4,二叉树的定义

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

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

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

相关文章

无涯教程-Perl - msgrcv函数

描述 此函数从队列ID接收消息,并将消息放入变量VAR中,最大大小为SIZE。 语法 以下是此函数的简单语法- msgrcv ID, VAR, SIZE, TYPE, FLAGS返回值 该函数在错误时返回0,在成功时返回1。 Perl 中的 msgrcv函数 - 无涯教程网无涯教程网提供描述此函数从队列ID接收消息,并将消…

山东布谷科技直播软件开发WebRTC技术:建立实时通信优质平台

在数字化的时代&#xff0c;实时通信成为了人们远程交流的主要方式&#xff0c;目前市场上也出现了很多带有实时通信交流的软件&#xff0c;实时通信符合人们现在的需求&#xff0c;所以在直播软件开发过程中&#xff0c;开发者也运用了实时通信技术为直播软件加入了实时通信的…

什么是CSS Grid布局?什么是Flexbox布局?它们两者有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS Grid布局⭐ Flexbox布局⭐ 不同之处⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web…

Chrome浏览器导出插件并安装到其他电脑浏览器上的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

说一下什么是tcp的2MSL,为什么客户端在 TIME-WAIT 状态必须等待 2MSL 的时间?

1.TCP之2MSL 1.1 MSL MSL:Maximum Segment Lifetime报文段最大生存时间&#xff0c;它是任何报文段被丢弃前在网络内的最长时间 1.2为什么存在MSL TCP报文段以IP数据报在网络内传输&#xff0c;而IP数据报则有限制其生存时间的TTL字段&#xff0c;并且TTL的限制是基于跳数 1.3…

【C++基础(十)】C++泛型编程--模板初阶

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 模板 1. 前言2. 函数模板3. 函数模板原理4. 函数…

2023年中国倍率型磷酸铁锂出货量及市场需求分析:插电混动汽车用电池为第一大应用市场[图]

由于新能源锂电池市场的竞争极其激烈&#xff0c;各大电池生产厂商不得不细化研发方向&#xff0c;抢占竞争者少、营利性高的细分专业赛道。因此&#xff0c;“自定义”型单体电池应运而生。其主要分为三个大类&#xff0c;分别为高倍率型电池、长寿命型电池和大容量型电池。这…

Linux安装Oracle数据库!

第一步&#xff0c;调试Linux虚拟机启动&#xff1a; 打开后&#xff0c;报错&#xff0c;如图&#xff1a; 解决&#xff1a; 步骤1&#xff1a;用管理员身份启动cmd&#xff0c;输入&#xff1a;bcdedit 查看hyper-v的状态&#xff0c;这里应该是off关闭状态。 步骤2&#…

cuda+anaconda+pytorch按照教程

首先安装显卡对应的CUDA版本&#xff0c;关键点在于区别显卡支持的CUDA最高版本和运行版本 1、查看当前显卡支持的最高版本&#xff0c;有两种方式&#xff1a; 1&#xff09;NVIDIA控制面板—>帮助—>系统信息—>组件—>NVCUDA.dll对应版本 请注意&#xff0c;12…

Java的switch语句块

说明 Java的switch语句块可以用于多个分支的判断执行。每个case分支执行完后&#xff0c;要么退出方法体&#xff08;用return语句&#xff09;、要么退出switch语句块&#xff08;用break语句&#xff09;、要么继续往下执行。但如果一个case执行完后&#xff0c;要继续执行下…

jQuery使用(超详细)

一、jQuery介绍 二、jQuery的简单使用 <head><meta charset"utf-8"><title></title><script type"text/javascript" src"../js/jquery-1.10.2.min.js"></script><script type"text/javascript"…

安装使用IDEA,修改样式,配置服务,构建Maven项目(超级详细版)

目录 前言&#xff1a; 一&#xff0c;安装 1.1打开官网JetBrains: Essential tools for software developers and teams点击 Developer Tools&#xff0c;再点击 Intellij IDEA 2.点击下载​编辑 3.选择对应的版本&#xff0c;左边的 Ultimate 版本为旗舰版&#xff0c;需要…

分割一切模型 Fast SAM C++推理部署---onnxruntime(有核心代码)

Fast SAM C推理部署—onnxruntime 核心源代码在结尾处 晓理紫 0 XX开局一张图&#xff0c;剩下… 本文记录只为日后更好学习 1 Fast SAM 简介 Fast SAM是仅使用SAM作者发布的SA-1B数据集的2%进行训练的CNN任意分割模型。FastSAM的性能与SAM方法相当&#xff0c;运行速度提高了…

概率论与数理统计:第二、三章:一维~n维随机变量及其分布

文章目录 Ch2. 一维随机变量及其分布1.一维随机变量1.随机变量2.分布函数 F ( x ) F(x) F(x)(1)定义(2)分布函数的性质 (充要条件)(3)分布函数的应用——求概率3.最大最小值函数 2.一维离散型随机变量及其概率分布(分布律)3.一维连续型随机变量及其概率分布(概率密度)4.一般类型…

Linux基础篇(五)文件权限

目录 一、文件权限的概念 二、Linux命令ll的结果解析 三、Linux修改权限的两种方法 四、更改文件的拥有者和所属组 五、身份的判定 六、系统掩码 七、删除文件需要的权限 八、粘滞位 一、文件权限的概念 1.是什么&#xff1f; 简单地说就是什么身份的用户能对文件做什么事。 …

如何在CSS中水平居中一个元素?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用 margin: 0 auto⭐ 使用 Flexbox 布局⭐ 使用绝对定位和负边距⭐ 使用表格布局⭐ 使用网格布局⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅…

【密码学】密码棒密码

密码棒密码 大约在公元前700年,古希腊军队使用一种叫做scytale的圆木棍来进行保密通信。其使用方法是这样的:把长带子状羊皮纸缠绕在圆木棍上,然后在上面写字;解下羊皮纸后,上面只有杂乱无章的字符,只有再次以同样的方式缠绕到同样粗细的棍子上,才能看出所写的内容。快速且不容…

STM32定时器TIM控制

一、CubeMX的设置 1、新建工程&#xff0c;进行基本配置 2、配置定时器TIM2 1&#xff09;定时器计算公式&#xff1a;&#xff08;以下两条公式相同&#xff09; Tout ((ARR1) * PSC1)) / Tclk TimeOut ((Prescaler 1) * (Period 1)) / TimeClockFren Tout TimeOut&…

选读SQL经典实例笔记23_读后总结与感想兼导读

1. 基本信息 SQL经典实例 SQL Cookbook [美]安东尼莫利纳罗&#xff08;Anthony Molinaro&#xff09; / 人民邮电出版社 / 2018-07 / 其他 人民邮电出版社,2018年7月出版第1版&#xff0c;2021年12月出版第2版 1.1. 读薄率 1版书籍总字数827千字&#xff0c;笔记总字数30…