【(C语言)数据结构奋斗100天】二叉树(上)

news2024/11/25 10:23:05

【(C语言)数据结构奋斗100天】二叉树(上)

🏠个人主页:泡泡牛奶

🌵系列专栏:数据结构奋斗100天

本期所介绍的是二叉树,那么什么是二叉树呢?在知道答案之前,请大家思考一下下列问题:

  1. 什么是二叉树的根节点?
  2. 什么是二叉树的左子树和右子树?
  3. 什么是二叉树的父节点和子节点?
  4. 二叉树的遍历有哪些方法?

让我们带着这些问题,开始今天的学习吧( •̀ ω •́ )✧

一、树和二叉树

1. 什么是树?

树是一种非线性的数据结构,是(n>=0)个节点的有限集合。当n=0时,称为空树。在任意一颗非空树中,我们可以看到节点的排列就像一颗倒着的树,根朝上,叶子朝下

367-3671401_bianry-tree-hd-png-download

在现实生活中有哪些像上面根朝上,叶子朝下的树型结构呢🤔?

wp7002672

例如一个家族里组成的 “家谱” ,就是一颗树。

再例如一个阶级关系就是一颗 “树”。

1634653354_378339_url

除开人与人的关系,还有很多抽象的东西也可以成为一颗 “树”,如一本书的目录,如操作系统的文件系统。

d0c50-linux2bfile2bsystem2bhierarchy

以上的共同点都是由一个 “根” 衍生出许多的 “枝干”,再从每一个 “枝干” 衍生出更多的 “叶子”。

在数据结构中,我们对树有以下称呼:

image-20230207195022422
  • 父节点/双亲节点:某节点的上一个节点为父节点,例如:C是F的父节点
  • (孩)子节点:某一节点指向的下一个节点为子节点,例如:F是C的子节点
  • 兄弟节点:父节点相同的节点互为兄弟节点,例如:D、E
  • 堂兄弟节点:双亲在同一层的节点互为堂兄弟,例如:D、F互为堂兄弟节点
  • 节点的:一个节点含有的子树的个数称为该节点的度,例如:B的度为2,C的度为1
  • 叶子节点度为0,或者无子节点的称为叶子节点,例如:G、E、F
  • 树的度:一颗树中的最大的节点的度,例如:上图树的度为2
  • 节点的层次根节点第一层, 依次类推
  • 树的高度/深度:树节点的最大层次,如上图树的高度为4
  • 节点的祖先:根节点到此节点的经过的所有节点都为祖先,例如:A是所有节点的祖孙
  • 子孙:只要在关系在某一节点的下面都为子孙
  • 森林:有(m > 0)的树所组成的集合称为森林

小结:

树的关系可以由现实生活中的亲戚关系来表示

2. 什么是二叉树?

什么是 n叉树

n叉树,故名思意,就是树的分叉最多可以有n个

8QA22

那么二叉树就是,最多有2个孩子节点的树。如下图所示。

image-20230207201745581

二叉树节点的两个孩子,一个被称为左孩子,一个被称为右孩子。这两个孩子的顺序是固定的。

3. 二叉树的类型

单二叉树的类型来说,其实有很多种,普通二叉树、满二叉树、完全二叉树、搜索二叉树、AVL树、红黑树……而今天我们的主题就是满二叉树和完全二叉树

一颗二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级上,那么这就是满二叉树,如下图。

满二叉树的总节点数为 S n = 2 n − 1 S_n = 2^{n}-1 Sn=2n1 (n为层数)

image-20230207212512657

对一个有n个节点的二叉树,按层级需要编号,则所有节点编号从1到n。如果这颗树的所有节点和同样深度的满二叉树的编号为1到n的节点位置相同,则这个二叉树为完全二叉树。如下图。(简单来说,最后一层连续排布,但不满就是完全二叉树)

image-20230207215651564

4. 二叉树的规律性质

image-20230207205933509
  • 这是一个公比为2的等比数列,首项为1。即 a 1 = 1 a_1=1 a1=1,公比 q = 2 q=2 q=2
  • 第n层节点的数量为 2 n − 1 2^{n-1} 2n1,前n层节点的数量总和为 S n = 2 n − 1 S_n=2^n-1 Sn=2n1
  • 对于任意一棵二叉树,满足 n = n 0 + n 1 + n 2 n=n_0+n_1+n_2 n=n0+n1+n2,其中 n n n 为节点总数, n 0 n_0 n0 表示度数为0的节点个数, n 1 n_1 n1 表示度数为1的节点个数, n 2 n_2 n2 表示度数为2的节点个数。
  • 存在 n 2 = n 0 − 1 n_2=n_0-1 n2=n01 的关系。
  • 计算层数 n n n 的公式为 n = log ⁡ 2 ( N + 1 ) n=\log_2(N+1) n=log2(N+1),其中 N N N 为节点总数。

上面这些规律往往会在刷题中使用到

二、二叉树的存储结构

链式结构和顺序结构是二叉树的两种常见存储方式。

1. 顺序结构

顺序存储结构使用数组作为基础存储单元,它适用于表示完全二叉树。除了堆,其他情况使用数组存储会则会造成大量空间浪费。顺序存储结构的二叉树在物理结构上是一个数组,逻辑结构上是一棵二叉树。

2019-05-16-10

用数组来存储,我们通常会通过下标来访问元素,观察节点规律,我们不难发现:

  • 若父节点为 father,子节点为 child,则满足:

    f a t h e r = c h i l d − 1 2 father = \frac{child - 1}{2} father=2child1

  • 若左右子节点分别为 leftright,并且左右孩子都存在(即 l e f t , r i g h t ≥ n left, right \ge n left,rightn),则满足:

    l e f t = f a t h e r ∗ 2 + 1 left = father * 2 + 1 left=father2+1

    r i g h t = f a t h e r ∗ 2 + 2 right = father * 2 + 2 right=father2+2

2. 链式结构

链式结构使用指针作为底层容器,通过指向子节点的指针来表示树的逻辑结构。这种方式在存储灵活性和空间利用效率方面优于顺序结构。通用方法是链表中每个节点由三个域组成:数据域和左右指针域。

typedef int treeType;//将int重定义为type_t
typedef struct TreeNode
{
    treeType val;			//表示数据
    TreeNode* left;	//表示左孩子
    TreeNode* right;	//表示右孩子
}TreeNode;

(图片)

总的来说,选择使用链式结构还是顺序结构要根据具体的存储需求来决定。

三、二叉树的遍历

当我们介绍数组、链表时,为什么没有着重研究他们的遍历过程呢?

二叉树的遍历又有什么特殊之处?

在计算机程序中,遍历线性结构的数组或链表是一件简单的事情。相反,二叉树是一种典型的非线性数据结构,遍历时需要将非线性关系的节点转化为线性序列。

二叉树的遍历可以根据节点的直接位置关系分为两类:

  1. 深度优先遍历(前序遍历、中序遍历、后续遍历)
  2. 广度优先遍历(层序遍历)

下面就来看看这些不同的遍历方式吧ο(=•ω<=)ρ⌒☆

1. 深度优先遍历

  1. 前序遍历

二叉树的前序遍历,遍历顺序为根节点、左子树、右子树,当遇到空指针NULL时返回。

二叉树1

代码示例如下:

void PreOrder(TreeNode* root)
{
    if (root == NULL)
    {
        return;
    }
    //先取出当前节点元素,再对其进行相关操作
    printf("%d", root->val);
    
    InOrder(root->left);//遍历左节点
    InOrder(root->right);//遍历右节点
}
  1. 中序遍历

二叉树的中序遍历,遍历顺序为左子树、根节点、右子树,当遇到空指针NULL时返回。

二叉树2

代码示例如下:

void InOrder(TreeNode* root)
{
    if (root == NULL)
    {
        return;
    }
    
    InOrder(root->left);//遍历左子树
    
    printf("%d", root->val);//取出元素,进行操作
    
    InOrder(root->right);//遍历右子树
}
  1. 后序遍历

二叉树的后序遍历,遍历顺序为左子树、右子树、根节点,当遇到空指针NULL时返回。

二叉树3

代码示例如下:

void PostOrder(TreeNode* root)
{
    if (root == NULL)
    {
        return;
    }
    
    PostOrder(root->left);//遍历左子树
    PostOrder(root->right);//遍历右子树
    printf("%d", root->val);//取出元素,进行操作
}

2. 广度优先遍历

广度优先遍历,按层次遍历,从根节点开始,按从上至下,从左至右的顺序遍历二叉树的所有节点。

使用广度优先算法,我们通常需要借用队列这个数据结构来实现(不知道队列的,或者没看过这篇文章的,赶紧取看看🚀传送门

接下来我们就会使用队列来完成我们所需要的操作。

二叉树4

这是上一期的队列节点结构,我们需要把QueueType的类型改为TreeNode*来存放我们的节点:

typedef TreeNode* QueueType;//改为TreeNode*

typedef struct QueueNode
{
    QueueType value;
    struct QueueNode* next;
}QueueNode;

而这也就是为什么我们需要对类型typedef的原因,可以方便我们做修改φ(゜▽゜*)♪

遍历代码示例如下:

void LevelOrder(TreeNode* root)
{
    Queue q;
    queue_init(&q);
    
    queue_push(&q, root);
    while (!queue_empty(&q))
    {
        TreeNode* cur = queue_front(&q);
        queue_pop(&q);
        if (cur == NULL)
        {
            continue;
        }
        printf("%d", cur->val);//取出元素,进行操作
        queue_push(&q, cur->left);
        queue_push(&q, cur->right);
    }
    
    //不要忘了释放Queue
    queue_destory(&q);
}

在刷题过程中,单纯只是这样,多半会有些不够,接下来我们就把代码进一步优化吧:

void LevelOrder(TreeNode* root)
{
    Queue q;
    queue_init(&q);
    
    int level = 0; //表示当前层数<------------
    queue_push(&q, root);
    while (!queue_empty(&q))
    {
        TreeNode* cur = queue_front(&q);
        queue_pop(&q);
        
//--------------------------------------------------
        int level_size = queue_size(&q);//获取当前层的元素个数
        for (int i = 0; i<level_size; ++i)
        {
            printf("%d", cur->val);//取出元素,进行操作
            
            //对当前节点的左右子节点进行判断,若为空便没有必要入队列
            if (cur->left != NULL)
            {
                queue_push(&q, cur->left);
            }
            if (cur->right != NULL)
            {
                queue_push(&q, cur->right);
            }
        }
//---------------------------------------------------
        
        ++level;//层数+1 <------------
    }
    
    //不要忘了释放Queue
    queue_destory(&q);
}

当每一层入完队列之后,队列内的元素个数一定是下一层的元素个数(可以简单的画一个图来看看,这里就给大家布置一个小问题,让你们自己来理解吧(*^-^*)

四、小结

二叉树是树形结构的一种,其中每个节点最多有两个子节点。二叉树有多种遍历方法,包括深度优先遍历和广度优先遍历。

深度优先遍历有三种:

  • 前序遍历
  • 中序遍历
  • 后序遍历

分别对应的遍历顺序为:

  • 根节点、左子树、右子树

  • 左子树、根节点、右子树

  • 左子树、右子树、根节点

广度优先遍历的遍历顺序是从上到下、从左到右

点赞是对博主的鼓励和支持!🤗 希望你们看完这篇博客后,不妨给博主一个大大的三连👍,表示对内容的赞赏!😊 当然,如果你是真心被内容打动,那么点个四连甚至五连都是博主最大的动力!💪 让我们一起用简单幽默的语气,为点赞助力!ο(=•ω<=)ρ⌒☆
题,让你们自己来理解吧(*^-^*)

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

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

相关文章

Window 10 OpenCV 打开罗技(Logitech)摄像头速度慢问题解决

采用最新版OpenCV 4.7.0 摄像头对罗技摄像头进行视频图像抓取时&#xff0c;发现存在打开摄像头问题。 测试环境如下&#xff1a; 系统Windows 10 专业版CPUIntel i7-7700K 4.20GHz 摄像头型号罗技Logitech C930c 网络摄像头OpenCV版本4.7.0语言C 测试结果表明&#xff1a; …

ASP.NET Core+Element+SQL Server开发校园图书管理系统(完)

随着技术的进步&#xff0c;跨平台开发已经成为了标配&#xff0c;在此大背景下&#xff0c;ASP.NET Core也应运而生。本文主要基于ASP.NET CoreElementSql Server开发一个校园图书管理系统为例&#xff0c;简述基于MVC三层架构开发的常见知识点&#xff0c;本系列共五篇文章&a…

抖yin获客系统简介,精准获取,系统简介

功能介绍功能获取获客系统主要核心数据看板名词介绍当前运行任务&#xff1a;系统正在运行的获客任务总数&#xff0c;获取客户档案&#xff1a;符合任务规则提取的目标客户&#xff0c;总分析任务&#xff1a;系统合计运行的获客任务&#xff0c;总视频数&#xff1a;符合任务…

QuickBuck:一款专为安全研究人员设计的勒索软件模拟器

关于QuickBuck QuickBuck是一款基于Golang开发的勒索软件模拟工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以通过更简单的方法来判断反病毒保护方案是否能够有效地预防勒索软件的攻击。 功能介绍 该工具能够模拟下列勒索软件典型行为&#xff0c;其中包括&a…

洛谷——P1091 合唱队形

【题目描述】 n 位同学站成一排&#xff0c;音乐老师要请其中的 n−k 位同学出列&#xff0c;使得剩下的 k 位同学排成合唱队形。 合唱队形是指这样的一种队形&#xff1a;设 kk 位同学从左到右依次编号为 1,2, … ,k&#xff0c;他们的身高分别为​,​, … ,​&#xff0c;则…

m序列发生器——Verilog设计

引言 本篇文章利用Verilog编写一个m序列发生器模块。本文会给出具体的设计、测试源码。 设计说明 模块功能说明: 支持任意位宽的随机数生成;支持本原多项式配置;支持初始种子配置;设计环境: 设计语言:Verilog HDL 设计验证平台:MATLAB R20222a、Vivado 2018.3 m 序列…

初识shell

文章目录一、shell基本知识1.1为什么学习和使用Shell编程1.2 什么是Shell1.2.1 shell的起源1.2.2 shell的功能1.3 shell的分类1.4 作为程序设计的语言——shell1.5 如何学好shell1.6 shell脚本的基本元素1.7 shell脚本编写规范1.8shell脚本的执行方式1.9 执行脚本的方法1.10 sh…

PPOJ刷题-3

PPOJ刷题-3 1265: 最近公共祖先 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&…

Elasticsearch7.8.0版本进阶——分布式集群(单节点集群)

目录一、Elasticsearch集群的安装1.1、Elasticsearch集群的安装&#xff08;win10环境&#xff09;1.2、Elasticsearch集群的安装&#xff08;linux环境&#xff09;二、单节点集群&#xff08;win10环境集群演示&#xff09;2.1、单节点集群的概述2.2、单节点集群的示例一、El…

On Joint Learning for Solving Placement and Routing in Chip Design

On Joint Learning for Solving Placement and Routing in Chip Design 目录On Joint Learning for Solving Placement and Routing in Chip Design一、整体思路和创新点二、相关工作2.1 partitioning-based methods&#xff08;基于分区的方法&#xff09;2.2 stochastic/hill…

Part 4 描述性统计分析(占比 10%)——中

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】【扩展知识——大数定律和中心极限定理】3、统计分布3.1、离散型随机变量的三种重要分布3.1.1、两点分布3.1.2、伯努利试验及二项分布3.1.2.1、伯努利试验3…

算法训练营 day39 贪心算法 无重叠区间 划分字母区间 合并区间

算法训练营 day39 贪心算法 无重叠区间 划分字母区间 合并区间 无重叠区间 435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互…

Early Stopping中基于测试集(而非验证集)上的表现选取模型的讨论

论文中一般都是用在验证集上效果最好的模型去预测测试集&#xff0c;多次预测的结果取平均计算准确率或者mAP值&#xff0c;而不是单纯的取一次验证集最好的结果作为论文的结果。如果你在写论文的过程中&#xff0c;把测试集当做验证集去验证的话&#xff0c;这其实是作假的&am…

shiro、springboot、vue、elementUI CDN模式前后端分离的权限管理demo 附源码

shiro、springboot、vue、elementUI CDN模式前后端分离的权限管理demo 附源码 源码下载地址 https://github.com/Aizhuxueliang/springboot_shiro.git 前提你电脑的安装好这些工具&#xff1a;jdk8、idea、maven、git、mysql&#xff1b; shiro的主要概念 Shiro是一个强大…

麻省理工出版 | 2023年最新深度学习综述手册

UCL Simon Prince的新书&#xff1a;《Understanding Deep Learning》 &#xff0c;在2023年2月6日由MIT Press出版。他之前写过很受欢迎的《Computer Vision: Models, Learning, and Inference》。 关于这本最新的深度学习手册&#xff0c;作者这样介绍它&#xff1a; 正如书…

数据结构与算法基础-学习-09-线性表之栈的理解、初始化顺序栈、判断顺序栈空、获取顺序栈长度的实现

一、个人理解栈是线性表的一种衍生&#xff0c;和之前的顺序表和链表在插入和删除元素上有较大差异&#xff0c;其他基本相同&#xff0c;栈是数据只能插入表的尾部&#xff08;栈顶&#xff09;&#xff0c;删除数据时只能删除表的尾部&#xff08;栈顶&#xff09;数据&#…

2022Q4手机银行新版本聚焦提升客群专属、财富开放平台、智能化能力,活跃用户规模6.91亿人

易观&#xff1a;2022年第4季度&#xff0c;手机银行APP迭代升级加快&#xff0c;手机银行作为零售银行服务及经营的主阵地&#xff0c;与零售银行业务发展的联系日益紧密。迭代升级一方面可以顺应零售银行发展战略及方向&#xff0c;对手机银行业务布局进行针对性调整优化&…

前端面经详解

目录 css 盒子充满屏幕 A.给div设置定位 B.设置html,body的宽高 C.相对当前屏幕高度&#xff08;强烈推荐&#xff09; 三列布局&#xff1a;左右固定&#xff0c;中间自适应 flex布局&#xff08;强烈推荐&#xff09; grid布局 magin负值法 自身浮动 绝对定位 圣…

基于PHP的招聘网站

摘要在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括在线招聘的网络应用&#xff0c;在外国在线招聘已经是很普遍的方式&#xff0c;不过国内的在线招聘可能还处于起步阶段。招聘网站具有招聘信息功能的双向选择&#xff0c;…

UMI入门(创建react项目)

1、umI的环境要求确保 node 版本是 10.13 或以上React 16.8.0 及以上的 React2、什么时候不用 umi需要支持 IE 8 或更低版本的浏览器需要支持 React 16.8.0 以下的 React需要跑在 Node 10 以下的环境中有很强的 webpack 自定义需求和主观意愿需要选择不同的路由方案3、与其他框…