[C/C++] -- 二叉树

news2024/11/28 3:52:21

1.简介

二叉树是一种每个节点最多有两个子节点的树结构,通常包括:根节点、左子树、右子树。

  • 满二叉树:

如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k - 1个节点。

  • 完全二叉树

除了最底层节点可能没填满外,其余每层节点数都达到最大值,且最下面一层节点都集中在该层最左边若干位置。若最底层为k层,则该层包含1~2^(k-1)个节点。

优先级队列其实是一个堆,堆就是一棵完全二叉树,同时保证父子节点的顺序关系。

  • 二叉搜索树

二叉搜索树有数值,是一个有序树。

若左子树不空,则左子树上所有节点值均小于根节点值。

若右子树不空,则右子树上所有节点值均大于根节点值。

左右子树分别为二叉搜索树

  • 平衡二叉搜索树

任意节点的左子树和右子树高度差不超过1,空树仅有一个节点,也是一种平衡二叉搜索树

C++种map、set、multimap、multiset的底层实现是平衡二叉搜索树(红黑树),所以增删时间复杂度O(logn),unordered_map、unordered_set底层实现是哈希表,理想情况具有O(1)的增删时间复杂度,最坏情况O(n)。

  • 二叉树存储方式

链式存储(指针)、顺序存储(数组)

二叉树定义:

#include <iostream>

// 定义二叉树节点结构
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

int main() {
    // 创建二叉树节点
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);

    // 访问二叉树节点的数值
    std::cout << "The value of the root node is: " << root->val << std::endl;
    std::cout << "The value of the left child of the root is: " << root->left->val << std::endl;

    // 释放二叉树节点的内存
    delete root->left->left;
    delete root->left->right;
    delete root->left;
    delete root->right;
    delete root;

    return 0;
}

2.二叉树遍历

常用于图论:

深度优先遍历:先往深走、遇到叶子节点再往回走。(前序、中序、后续遍历:递归法、迭代法)

广度优先遍历:一层一层的去遍历。(层次遍历:迭代法)

前中后指的是中间节点遍历顺序

前序:中左右          5 4 1 2 6 7 8

中序:左中右          1 4 2 5 7 6 8

后序:左右中          1 2 4 7 8 6 5

递归法: 

 前序遍历:

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> 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);        
        traversal(cur->right,vec);
        vec.push_back(cur->val);
    }
    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;
        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;
    }
};

中序遍历

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()){
           if (cur != NULL){
                st.push(cur);
                cur = cur->left;
            }else{
                cur = st.top();
                st.pop();
                result.push_back(cur->val);
                cur = cur->right;
            }
        }
        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->left) st.push(node->left);
            if (node->right) st.push(node->right);
        }
        reverse(result.begin(),result. End());
        return result;
    }
};

3.例题

示例 1:

输入:root = [1,7,0,7,-8,null,null]
输出:2
解释:
第 1 层各元素之和为 1,
第 2 层各元素之和为 7 + 0 = 7,
第 3 层各元素之和为 7 + -8 = -1,
所以我们返回第 2 层的层号,它的层内元素之和最大。

示例 2:

输入:root = [989,null,10250,98693,-89388,null,null,null,-32127]
输出:2
  • 深度优先搜索 

/**
 * 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 {
    vector<int> sum;
    void dfs(TreeNode* node,int level){
        if(sum.size() == level){
            sum.push_back(node->val);
        }else{
            sum[level]+=node->val;
        }
        if(node->left){
            dfs(node->left,level+1);
        }
        if(node->right){
            dfs(node->right,level+1);
        }
    }

public:
    int maxLevelSum(TreeNode* root) {
        dfs(root,0);
        int ans = 0;
        for(int i = 0;i<sum.size();i++){
            if(sum[i]>sum[ans]){
                ans = i;
            }
        }
        return ans+1;
    }
};
  • 广度优先搜索
/**
 * 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:
    int maxLevelSum(TreeNode* root) {
        int ans = 1,maxSum = root->val;
        vector<TreeNode*q> = {root};
        for(int level = 1;!q.empty();++level){
            vector<TreeNode*> nq;
            int sum = 0;
            for (auto node:q) {
                sum +=node->val;
                if (node->left){
                    //用于在容器尾部直接构造一个新元素,可以避免额外的拷贝或移动操作。
                    nq.emplace_back(node->left);
                }
                if(node->right){
                    nq.emplace_back(node->right);
                }
            }
            if (sum > maxSum) {
                maxSum = sum;
                ans = level;
            }
            //通过 move(nq),我们将 nq 的所有权(ownership)转移给 q。
            //这意味着实际上并不会进行元素的复制,而是直接将 nq 中的元素转移到 q 中,同时 nq 被置为空。
            q = move(nq);
        }
        return ans;
    }
};

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

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

相关文章

10、电科院FTU检测标准学习笔记-双遥信及变位优先验证

———————————————————————————————————— 作者简介&#xff1a; 本人从事电力系统多年&#xff0c;岗位包含研发&#xff0c;测试&#xff0c;工程等&#xff0c;具有丰富的经验 在配电自动化验收测试以及电科院测试中&#xff0c;本人全程参…

电脑win10系统更新后开机很慢,更新win10后电脑开机怎么变慢了

很多用户反映,更新win10后电脑开机怎么变慢了呢?现在动不动就要30几秒,以前都是秒开机的,要怎么设置才能提高开机速度?小伙伴们别着急,主要原因可能是关机设置中没有勾选启用快速启动,或者是开机启动设置的问题,针对开机变慢的情况,小编整理了2个处理方法,接下来,我…

U盘PE引导-系统安装操作

U盘PE引导-系统安装操作 1. U盘接入电脑&#xff0c;开机按F12&#xff08;DELL&#xff09;选择U盘引导&#xff0c;按回车&#xff0c;如图2.选择进入PE 系统3.进入PE 系统后&#xff0c;运行 WinNTSetup 安装器&#xff0c; 具体 设置如下图 1. U盘接入电脑&#xff0c;开机…

C语言键盘输入与屏幕输出——数据的格式化键盘输入

目录 数据的格式化键盘输入 输入数据的格式控制 scanf&#xff08;&#xff09;的格式字符 scanf()的格式修饰符 数据的格式化键盘输入 格式 scanf&#xff08;格式控制字符串&#xff0c;输入地址表&#xff09;&#xff1b; 输入数据的格式控制 格式 scanf&#xff08;…

深度学习:AIGC重塑金融大模型驱动金融变革

作者&#xff1a;林建明 来源&#xff1a;IT阅读排行榜 本文摘编自《AIGC重塑金融&#xff1a;AI大模型驱动的金融变革与实践》&#xff0c;机械工业出版社出版这是最好的时代&#xff0c;也是最坏的时代。尽管大模型技术在金融领域具有巨大的应用潜力&#xff0c;但其应用也面…

Stream流的详细说明

什么是stream流 Stream流是指一种数据处理的概念&#xff0c;它可以将数据以连续的方式传输&#xff0c;而不用等待整个数据集全部加载完成。在计算机编程中&#xff0c;Stream流通常用于处理大数据集或实时数据流。 Stream流可以分为输入流和输出流&#xff0c;输入流用于从数…

Python 唯一标识符(UUID)库之shortuuid使用详解

概要 在现代软件开发中,唯一标识符(UUID)在数据记录、身份验证和唯一性标识等方面扮演着重要的角色。然而,标准的UUID通常很长,不方便使用。Python的shortuuid库应运而生,它可以生成短且易读的唯一标识符,方便在各种应用场景中使用。本文将深入探讨shortuuid库的特性、…

Docker Desktop 在 Windows 上的安装和使用

目录 1、安装 Docker Desktop 2、使用 Docker Desktop &#xff08;1&#xff09;运行容器 &#xff08;2&#xff09;查看容器信息 &#xff08;3&#xff09;数据挂载 Docker Desktop是Docker的官方桌面版&#xff0c;专为Mac和Windows用户设计&#xff0c;提供了一个简…

第3章 数据链路层(2)

3.4 流量控制和可靠传输机制 数据链路层流量控制控制相邻节点发送速率。 使用确认和超时重传两种机制实现可靠传输。 3.4.1 流量控制,可靠传输与滑动窗口机制 1.停止—等待协议协议基本原理 发送方发每发送一帧,等待接收方回应的ACK发送下一帧或超出计时没收到ACK就重发。 2.滑…

将python项目封装打包为.so文件(多级目录)

原始目录 segment-anything文件夹 结果目录 删除了用于测试、说明的相关文件&#xff0c;更改了一些文件名称&#xff0c;使用main.py作为入口程序。 segment-anything文件夹 具体实现 1.删除不必要的文件 2.改segment-anything为seg 3.改amg_test.py 改test.py 改./seg/pr…

4.java openCV4.x 入门-Mat之创建、复制

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;我们唯一拥有的就是今天&#xff0c;唯一能把握的也是今天建议把本文当作笔记来看&#xff0c;据说专栏目录里面有相应视频&#x1f92b; &#x1f9ed;文…

C# 高级文件操作与异步编程探索(初步)

文章目录 文本文件的读写探秘StreamReader 类深度剖析StreamWriter 类细节解读编码和中文乱码的解决方案 二进制文件的读写BinaryReader 类全面解析BinaryWriter 类深度探讨 异步编程与C#的未来方向同步与异步&#xff1a;本质解读Task 的神奇所在async/await 的魔法 在现代编程…

window配置RUST开发环境详解

1.先安装VS2022: 下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux (microsoft.com) 2.下载Rustup-init.exe Other Installation Methods - Rust Forge 3.运行rustup-init.exe开始安装rust开发环境: 安装成功出现下图所示 %USERPROFILE%\.cargo\bin 添加cargo安装路…

mysql 本地电脑服务部署

前提&#xff1a; 下载mysql 新建配置文档 在安装mysql目录新建 my.ini [mysqld] # 设置3306端口 port3306#设置mysql的安装目录 basedirC:\Program Files\MySQL\MySQL Server 8.3 #切记此处一定要用双斜杠\\,单斜杠我这里会出错&#xff0c;不过看别人的教程&#xff0c;有…

【软件工程】详细设计(一)

1. 引言 1.1 编写目的 该文档的目的是描述《学生成绩管理系统》项目的详细设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统详细设计简述 各个模块的实现逻辑 最小模块组件的伪代码 本文档的预期的读者是&#xff1a; 开发人员 项目管理人员 测试人员 …

Spring(详细介绍)

目录 一、简介 1、什么是Spring&#xff1f; 2、Spring框架的核心特性 3、优点 二、IOC容器 介绍 1、获取资源的传统方式 2、控制反转方式获取资源 3、DI 4、IOC容器在Spring中的实现 入门案例 1、创建Maven Module 2、引入依赖 3、创建HelloWorld类 4、在Spring的配…

Linux------一篇博客了解Linux最常用的指令【后续将持续更新完成】

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;Linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

HarmonyOS 应用开发之多端协同

多端协同流程 多端协同流程如下图所示。 图1 多端协同流程图 约束限制 由于“多端协同任务管理”能力尚未具备&#xff0c;开发者当前只能通过开发系统应用获取设备列表&#xff0c;不支持三方应用接入。 多端协同需遵循 分布式跨设备组件启动规则。 为了获得最佳体验&…

春招冲刺百题计划--矩阵篇

289. 生命游戏 题目&#xff1a; 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即为 活细胞 &#xff08;live&#xff09;&#xff0c;或 0 即为 死细胞 &#xff08;dead&#xff09;。每个细胞与…

mysql执行脚本导入表和数据后中文注释乱码解决

本人在使用不同版本下进行操作时&#xff0c;就会出现中文乱码的问题。例如我本地安装mysql8&#xff0c;服务器安装的是mysql5&#xff0c;然后本地连接服务器的mysql后&#xff0c;执行SQL脚本之后发现中文全部乱码 使用工具查看&#xff0c;注释也都是乱码 解决方案 本地…