【数据结构】二叉树知识点详解

news2024/11/25 20:49:22

树的概念

  • 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合
  • 有一个特殊的结点,称为根结点,根节点没有前驱结点
  • 除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i<= m)又是一棵结构与树类似的子树

image.png
注意:树形结构中,子树之间不能有交集,否则就不是树形结构

树的相关概念

image.png

  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 如上图:A的为6叶节点或终端节点**,度为0的节点称为叶节点**;
  • 如上图:B、C、H、I…等节点为叶节点非终端节点或分支节点:度不为0的节点
  • 如上图:D、E、F、G…等节点为分支节点双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
  • 如上图:A是B的父节点孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
  • 如上图:B是A的孩子节点兄弟节点:具有相同父节点的节点互称为兄弟节点;
  • 如上图:B、C是兄弟节点树的度:一棵树中,最大的节点的度称为树的度;
  • 如上图:树的度为6节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推树的高度或深度:树中节点的最大层次;
  • 如上图:树的高度为4堂兄弟节点:双亲在同一层的节点互为堂兄弟;
  • 如上图:H、I互为兄弟节点节点的祖先:从根到该节点所经分支上的所有节点;
  • 如上图:A是所有节点的祖先子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
  • 如上图:所有节点都是A的子孙森林:由m(m>0)棵互不相交的树的集合称为森林

二叉树概念及结构

概念

image.png
一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成
  3. 二叉树不存在度大于2的结点
  4. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
二叉树的状态

image.png

特殊的二叉树

image.png

  • 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是,则它就是满二叉树
  • 完全二叉树:对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
二叉树的性质
  • 规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2(i-1) 个结点
  • 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2的h次方- 1
  • 对任何一棵二叉树,如果度为0其叶结点个数为 n1,度为2的分支结点个数为 n2,则有n1=n2+1
  • 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1)–(ps:log2(n + 1)是log以2为底n+1为对数)
  • 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于席号为i的结点有:

关系位置

  1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
  2. 若2i+1=n否则无左孩子
  3. 若2i+2=n否则无右孩子

二叉树的存储结构

顺序存储
  • 顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。
  • 而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

image.png

链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。
image.png

遍历过程

先序遍历

image.png

非递归遍历
class Solution {
public:
    void inorder(TreeNode*root,vector<int>&v)
    {
        if(root==nullptr)return;
        
        v.push_back(root->val);
        inorder(root->left,v);
        inorder(root->right,v);
        
        

    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>v;
        if(!root)return v;
        inorder(root,v);

    return v;
    }
};
非递归遍历(栈)
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int >v;
        stack<TreeNode*>st;
        TreeNode*cur=root; //拷贝一个节点 避免把根节点给删除

        while(cur || !st.empty()) //判断栈是否为空,节点是否为空
        {
            while(cur) //先遍历到最左节点 把节点都压栈
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode*top=st.top(); //取栈顶的节点
            v.push_back(top->val);//取值到vtor
            st.pop();//删除栈中的节点
            cur=top->right;//然后就遍历右节点
        }
        return v;
    }
};
中序遍历

image.png

递归遍历
class Solution {
public:
    void inorder(TreeNode*root,vector<int>&v)
    {
        if(root==nullptr)return;
        
        
        inorder(root->left,v);
        v.push_back(root->val);
        inorder(root->right,v);

    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>v;
        if(!root)return v;
        inorder(root,v);

    return v;
    }
};
非递归遍历(栈)
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int >v;
        stack<TreeNode*>st;
        TreeNode*cur=root; //拷贝一个节点 避免把根节点给删除

        while(cur || !st.empty()) //判断栈是否为空,节点是否为空
        {
            while(cur) //先遍历到最左节点 把节点都压栈
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode*top=st.top(); //取栈顶的节点
            v.push_back(top->val);//取值到vtor
            st.pop();//删除栈中的节点
            cur=top->right;//然后就遍历右节点
        }
        return v;
    }
};
后序遍历

image.png

递归遍历
class Solution {
public:
    void inorder(TreeNode*root,vector<int>&v)
    {
        if(root==nullptr)return;
        
        
        inorder(root->left,v);
        inorder(root->right,v);
        v.push_back(root->val);
        
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>v;
        if(!root)return v;
        inorder(root,v);

    return v;
    }
};
非递归遍历(栈)
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode* >st; 
        vector<int>v;
        TreeNode*cur=root;    //拷贝节点
        TreeNode*prev=nullptr;    

        while(cur||!st.empty())  
        {
            while(cur)   //存储根到最左的所有节点
            {
                st.push(cur);
                cur=cur->left;
            }

           TreeNode*top=st.top();      //记录最左节点

            //如果他的右是空那么他的左右都没有子节点了,这时就可以进数据 ;
            //top->right==prev 这里保证了右节点的插入数据,记录上一个经过的节点
            if(top->right==nullptr||top->right==prev)    
            {
                v.push_back(top->val);
                st.pop();
                prev=top;                   //记录上一个节点
            }
            else
            {
                cur=top->right;      
            }
        }
    return v;
    }
};
层次遍历

image.png

非递归遍历(队列)
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        
        //层序遍历   同深度的一个集合
        vector<vector<int>> v; //存放每一层的数据
        if(!root)
        {
            return v;
        }
        queue<TreeNode*> q; 
        q.push(root);

        while(!q.empty())//这里一直不为空
        {   
            int ret=q.size();//计算当前层的节点个数
            vector<int>cur;
            while(ret--)
            {
                TreeNode*node =q.front();//头部为左节点
                q.pop();
                cur.push_back(node->val);//取节点值
                if(node->left) 
                    q.push(node->left); //取左节点
                if(node->right) 
                    q.push(node->right);//取右节点
            }
            v.push_back(cur);
        }
        return v;
    }
};
方法2
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        
        queue <TreeNode*>q;
        int size=0;
        if(root)
        {
            q.push(root);
            size=1;
        }
        
    vector<vector<int>> vv;
    while(!q.empty())
    {
        vector<int>v;
        while(size--) //每一层的个数
        {
            TreeNode* t=q.front();
            q.pop();
            v.push_back(t->val);

            if(t->left)
                q.push(t->left);
            if(t->right)
                q.push(t->right);
        }
        vv.push_back(v);
        size=q.size();//更新
    }
    return vv;
    }
};

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

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

相关文章

【busybox记录】【shell指令】expand

目录 内容来源&#xff1a; 【GUN】【expand】指令介绍 【busybox】【expand】指令介绍 【linux】【expand】指令介绍 使用示例&#xff1a; 把制表符转化为空格 - 默认输出 把制表符转化为空格 - 修改制表符转空格的个数 把制表符转化为空格 - 修改制表符转空格的个数…

git bash各分支修改内容不同但合并后不显示冲突问题

在跟着廖雪峰老师的git学习时&#xff0c;按部就班的执行明后&#xff0c;发现 而不是出现原文的结果 解决方法&#xff1a; 切换位feature分支&#xff0c;再合并 git switch feature1 git merge master 此时我们发现&#xff1a; 后面再跟着原文敲就可以了

CSS学习笔记之基础教程(二)

上节内容CSS学习笔记之基础教程&#xff08;一&#xff09; 6、边距 6.1 外边距&#xff1a;margin 6.1.1 外边距 marginmargin-topmargin-leftmargin-bottommargin-right <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8…

python-scrapy框架示例

参考&#xff1a;https://blog.csdn.net/qq_44907926/article/details/119531324 创建项目步骤&#xff1a; 1.目标网站:www.itcast.cn 2.安装虚拟环境 pip install virtualenv3.创建虚拟环境 virtualenv --always-copy --system-site-packages venv4.激活虚拟环境 venv\sc…

OCR文本识别模型CRNN

CRNN网络结构 论文地址&#xff1a;https://arxiv.org/pdf/1507.05717 参考&#xff1a;https://blog.csdn.net/xiaosongshine/article/details/112198145 git:https://github.com/shuyeah2356/crnn.pytorch CRNN文本识别实现端到端的不定长文本识别。 CRNN网络把包含三部分&…

推荐5个免费的国内平替版GPT

提起AI&#xff0c;大家第一个想到的就是GPT。 虽然它确实很厉害&#xff0c;但奈何于我们水土不服&#xff0c;使用门槛有些高。 不过随着GPT的爆火&#xff0c;现在AI智能工具已经遍布到各行各业了&#xff0c;随着时间的推移&#xff0c;国内的AI工具也已经“百花盛放”了…

简单了解泛型

基本数据类型和对应的包装类 在Java中, 基本数据类型不是继承自Object, 为了在泛型代码中可以支持基本类型, Java给每个基本类型都对应了一个包装类型. 简单来说就是让基本数据类型也能面向对象.基本数据类型可以使用很多方法, 这就必须让它变成类. 基本数据类型对定的包装类…

Istio 流量管理(请求路由、流量转移、请求重试、流量镜像、故障注入、熔断等)介绍及使用

一、Istio 流量管理 Istio是一个开源的服务网格&#xff0c;它为分布式微服务架构提供了网络层的抽象。它使得服务之间的通信变得更为可靠、安全&#xff0c;并且提供了细粒度的流量管理、监控和策略实施功能。Istio通过在服务之间插入一个透明的代理&#xff08;Envoy&#x…

Unreal游戏GPU参数详解,游戏性能优化再升级

UWA GOT Online For Unreal GPU模式近期全新发布&#xff0c;方便开发者从渲染和带宽的角度进行GPU分析。同时&#xff0c;此次更新中UWA也增加了丰富的GPU参数&#xff0c;涵盖了GPU SoC和GPU Counter模块。这些新增的参数不仅能够帮助Unreal开发者从宏观层面监控GPU的压力状况…

QT-TCP通信

网上的资料太过于书面化&#xff0c;所以看起来有的让人云里雾里&#xff0c;看不懂C-tcpsockt和S-tcpsocket的关系 所以我稍微画了一下草图帮助大家理解两个套接字之间的关系。字迹有的飘逸勉强看看 下面是代码 服务端&#xff1a; MainWindow::MainWindow(QWidget *parent) …

Jira Server 不维护了,如何将 Jira 平滑迁移到阿里云云效

作者&#xff1a;天彤 Atlassian 在 2020 年官方发布公告&#xff0c;从 2021 年起停止 Jira Server 产品的销售&#xff0c;并且在 2024 年彻底停止 Server 端产品的服务支持&#xff0c;这对于国内使用 Jira 产品的企业和研发团队造成了不小的影响。而此时国内很多 DevOps 产…

本地主机访问服务器的Redis -- 配置 ssh 端口转发

前言 在进行Java开发时&#xff0c;高度的依赖 Windows 上的开发软件 idea &#xff0c;那么我们想访问位于服务器上的 redis 怎么办呢&#xff1f;在平时我们想访问位于服务器上的程序&#xff0c;只需要开放它的端口即可&#xff0c;比如我们创建的网站&#xff0c;比如 tomc…

【拆位法 决策包容性 位运算】2871. 将数组分割成最多数目的子数组

本文涉及知识点 拆位法 贪心 位运算 决策包容性 位运算、状态压缩、子集状态压缩汇总 LeetCode2871. 将数组分割成最多数目的子数组 给你一个只包含 非负 整数的数组 nums 。 我们定义满足 l < r 的子数组 nums[l…r] 的分数为 nums[l] AND nums[l 1] AND … AND nums[r…

使用图网络和视频嵌入预测物理场

文章目录 一、说明二、为什么要预测&#xff1f;三、流体动力学模拟的可视化四、DeepMind神经网络建模五、图形编码六、图形处理器七、图形解码器八、具有不同弹簧常数的轨迹可视化九、预测的物理编码和推出轨迹 一、说明 这是一篇国外流体力学专家在可视化流体物理属性的设计…

如何使用vue脚手架创建项目

前言 使用vue搭建项目的时候&#xff0c;我们可以通过对应的cmd命令去打开脚手架&#xff0c;然后自己配置对应的功能插件 说明&#xff1a; 要使用Vue脚手架创建项目&#xff0c;你需要先确保你已经安装了Node.js和npm&#xff08;Node.js的包管理器&#xff09;。然后&#…

Github 2024-05-07 开源项目日报 Tp10

根据Github Trendings的统计,今日(2024-05-07统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目4Jupyter Notebook项目2Python项目1Batchfile项目1非开发语言项目1Java项目1HTML项目1C#项目1从零开始构建你喜爱的技术 创建周期…

性能测试基础介绍

1.性能测试的意义 1.1.现状 互联网行业发展快&#xff0c;用户量大大增加&#xff1b; 业务和系统架构越来越复杂&#xff0c;数据越来越多&#xff0c;用户不仅仅满足于功能的实现&#xff0c;在某些场景下&#xff0c;更 在意系统性能。 1.2.什么是性能测试 通过一定的手段&…

Google准备好了吗?OpenAI发布ChatGPT驱动搜索引擎|TodayAI

在科技界波澜壮阔的发展中&#xff0c;OpenAI正式宣布其最新突破——一个全新的基于ChatGPT技术的搜索引擎&#xff0c;旨在直接挑战谷歌在搜索领域的统治地位。这一创新将可能彻底改变用户上网搜索的方式。 据悉&#xff0c;这款AI驱动的搜索引擎利用了ChatGPT的强大功能&…

快速搭建linux虚拟机环境

1、虚拟机资源 VMwareWorkstation&#xff1a;Download VMware Workstation Pro virtualbox&#xff1a;Oracle VM VirtualBox 2、虚拟机系统资源 链接&#xff1a;系统资源链接 提取码&#xff1a;0gat 说明&#xff1a;此处的系统资源是采用VMwareWorkstation 虚拟机进…

【postgreessql 】查询数据库表占用物理空间

查询单个表的磁盘使用量&#xff1a; SELECTrelname,pg_size_pretty ( pg_total_relation_size ( relid ) ) AS total_size FROMpg_catalog.pg_statio_user_tables; 查询所有表的总磁盘使用量&#xff1a; SELECTpg_size_pretty ( SUM ( pg_total_relation_size ( relid ) )…