【数据结构】| 王道考研——树的前世今生

news2024/11/26 12:20:06

目录

  • 一. 🦁 前言
  • 二. 🦁 各种树的知识点
    • 1. 树
      • 1.1 概念
      • 1.2 属性
      • 1.3 常考性质
      • 1.4 树转换成二叉树
      • 1.5 森林转换为二叉树
      • 1.6 二叉树转换为森林
      • 1.7 树的遍历
      • 1.8 森林的遍历
    • 2. 二叉树
      • 2.1满二叉树
      • 2.2 完全二叉树
      • 2.3二叉排序树
      • 2.4 平衡二叉树
      • 2.5 二叉树常考性质
      • 2.6 二叉树存储结构
        • 1. 顺序存储
        • 2. 链式存储
      • 2.7二叉树的遍历
        • 1. 先序遍历
        • 2. 中序遍历
        • 3. 后序遍历
        • 4. 层序遍历
    • 3. 线索二叉树
    • 4. 哈夫曼树与哈夫曼编码
      • 4.1 哈夫曼树的构造
    • 5. 并查集
      • 5.1 初始版本
      • 5.2 优化版本
  • 三. 🦁 总结

一. 🦁 前言

根据王道考研数据结构总结出的知识点,以下是文章整体大纲:

image-20230723130110176

二. 🦁 各种树的知识点

1. 树

1.1 概念

树是n个结点的有限集合,n = 0时称为空树,这是一种特殊情况。任意一棵非空树中应满足:

  • 有且仅有一个特定的称为根的节点
  • 当n>1时,其余结点可分为m个互不相交的有限集合T1、T2、T3……Tm;每个集合又称为根结点的子树。

1.2 属性

  • 结点的深度:从上往下数;

  • 结点的高度:从下往上数;

  • 树的高度:总共多少层

  • 结点的度:有几个孩子

  • 树的度:树中结点的度的最大值

1.3 常考性质

  • 结点数 = 总度数+1
  • 度为m的树和m叉树

度为m的树是一定存在一个结点,它的度为m,且树非空;m叉树是指任意结点的度≤m,可以为空;

  • 度为m的树第i层至多有m的i-1次方个结点(i>=1)
  • image-20230723143113059
  • 高度为h的m叉树至少有h个结点;高度为h,度为m的树至少有h+m-1个结点。
  • image-20230723143347321

1.4 树转换成二叉树

image-20230724100900988

树转换成二叉树的画法:

  • 在兄弟结点之间加一条线;
  • 对每个结点,只保留它与第一个孩子的连线,抹去与其他孩子的连线;
  • 以树根为轴心,顺时针旋转 45°

image-20230724101120106

image-20230724101132179

1.5 森林转换为二叉树

image-20230724101527000

森林转换成二叉树的画法:

  • 将森林中的每棵树转换成相应的二叉树
  • 每棵树的根也可视为兄弟结点,在每棵树之间加一根连线
  • 以第一棵树的根为轴心顺时针旋转 45°

image-20230724101601740

image-20230724101623057

image-20230724101643384

1.6 二叉树转换为森林

image-20230724101948080

就是将森林转换为二叉树的逆做法

image-20230724102342490

image-20230724102411236

image-20230724102431012

image-20230724102446379

1.7 树的遍历

树的遍历: 用某种方式访问树中的每个结点,且仅访问一次

先序遍历:先根后子树

后根遍历:先子树后根

先根遍历序列为:ABEFCDG 对应二叉树中的先序遍历

后根遍历序列为:EFBCGDA 对应二叉树中的中序遍历

1.8 森林的遍历

先序遍历:先根后子树

中序遍历:先子树后根

image-20230724104049284

先序遍历序列为:ABCDEFGHI 对应二叉树的先序遍历

中序遍历序列为:BCDAFEHIG 对应二叉树的中序遍历

2. 二叉树

二叉树是n个结点的有限集合;

2.1满二叉树

一棵高度为h,且含有2的h次方-1个结点的二叉树;

image-20230723145100173

特点:

  • 只有最后一层有叶子结点;
  • 不存在度为1的结点;
  • 按层序从1开始编号,结点为i的左孩子结点为2i;右孩子为2i+1;结点i的父结点为i/2;

2.2 完全二叉树

当且仅当每个结点都与高度为h的满二叉树中编号为1~n的结点一一对应时,称为完全二叉树;

特点:

  • 只有最后两层可能有叶子结点;
  • 最多只有一个度为1的结点;
  • i ≤ n/2为分支结点,i > n/2为叶子结点;
  • 如果一个完全二叉树某结点只有一个孩子,则这个一定是左孩子;

2.3二叉排序树

  • 左子树的所有结点均小于根结点;
  • 右子树的所有结点均大于根结点;
  • 左子树和右子树又各是一棵二叉排序树

2.4 平衡二叉树

树上任一结点的左子树和右子树的深度之差不超过1;

image-20230723160447616

2.5 二叉树常考性质

  • 设非空二叉树中度为0、度为1、度为2的结点个数分别为n0、n1、n2,则n0 = n2 +1(叶子结点永远比二分支结点多一个);
  • image-20230723161341023
  • image-20230723161405345
  • image-20230723161855103

image-20230723162257413

2.6 二叉树存储结构

1. 顺序存储

使用数组实现顺序存储。一定要把二叉树的结点编号与完全二叉树对应起来。

  • i 的左孩子 — 2i+1
  • i 的右孩子 — 2i+2
  • i 的父节点 — 『(i-1)/2』

2. 链式存储

struct ElemType{
	int value;
}
typedef struct BiTNode{
	ElemType data;		//数据域
	struct BiTNode *lchild;		//左孩子指针
	struct BiTNode *rchild;		//右孩子指针
}BiTNode,*BiTree;

假设二叉树有n个结点,那么一定会有2n个指针,共有n+1个空链域;

二叉树操作:

// 定义一棵空树
BiTree root = null;
// 插入根节点
root = (BiTree) malloc(sizeof(BiTNode));
root->data = {1};
root->lchild = NULL;
root->rchild = NULL;

//插入新结点
BiTNode * p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = {2};
p->lchild = NULL;
p->rchild = NULL;
root->lchild = p;		//作为根节点的左孩子

image-20230723180915078

2.7二叉树的遍历

1. 先序遍历

先序遍历(preOrder)的操作过程如下:

  • 若二叉树为空,则什么也不做

  • 若二义树非空:

    • 访问根结点
    • 先序遍历左子树
    • 先序遍历右子树
    void preOrder(BiTree root){
    	if(root != null){
    		visit(root);			//访问根节点操作
    		preOrder(root->lchild);
    		preOrder(root->rchild);
    	}
    }
    
    void preOrder(BiTree root){
    	if(root != null){
    		visit(root);			//访问根节点操作
    		preOrder(root->lchild);
    		preOrder(root->rchild);
    	}
    }
    

    image-20230723183809469

    如下: 每个结点都会被访问三次。

    image-20230723183904781

2. 中序遍历

中序遍历(inOrder)的操作过程如下:

  • 若二叉树为空,则什么也不做
  • 若二义树非空:
    • 中序遍历左子树
    • 访问根结点
    • 中序遍历右子树
void inOrder(BiTree root){
	if(root != null){
		inOrder(root->lchild);
        visit(root);			//访问根节点操作
		inOrder(root->rchild);
	}
}

3. 后序遍历

后序遍历(postOrder)的操作过程如下:

  • 若二叉树为空,则什么也不做
  • 若二义树非空:
    • 后序遍历左子树
    • 后序遍历右子树
    • 访问根节点
void postOrder(BiTree root){
	if(root != null){
		postOrder(root->lchild);
		postOrder(root->rchild);
        visit(root);			//访问根节点操作
	}
}

image-20230723184101816

应用:求树的深度

image-20230723184436820

4. 层序遍历

算法思想:

  • 初始化一个辅助队列
  • 根结点入队
  • 若队列非空,则队头结点p出队,访问p,并将其左右孩子插入队尾(如果有的话)
  • 重复步骤3,直到队列为空。

// 层序遍历

void levelOrder(BiTree root){
	LinkQueue queue;			
	InitQueue(queue);			//初始化队列
	BiTree p;
	enQueue(root);				//根节点入队
	while(!isEmpty(queue)){		//队列不为空则循环
		deQueue(queue,p);		//队头结点出队
		visit(p);
		if(p->lchild != NULL) enQueue(queue,p->lchild);
		if(p->rchild != NULL) enQueue(queue,p->rchild);
	}
}

队列定义如下:

image-20230723190510939

3. 线索二叉树

4. 哈夫曼树与哈夫曼编码

权: 树中结点常被赋予一个代表某种意义的数值;

结点带权路径长度: 从树的根到任意结点的路径长度与该结点上权值的乘积;

image-20230724105438291

哈夫曼树: 带权路径长度最小的二叉树

4.1 哈夫曼树的构造

构造哈夫曼树的步骤:

  • 将所有结点分别作为仅含一个结点的二叉树;
  • 构造一个新结点,从中选取两棵根结点权值最小的树作为新结点的左、右子树,并且将新结点的权值置为左、右子树上根结点的权值之和;(意思即 每次找出两个权值最小的组成一棵二叉树
  • 从中删除刚才选出的两棵树,同时将新得到的树加入森林中;
  • 重复步骤(2) 和 (3),直至剩下一棵树为止

image-20230724105756389

  1. image-20230724110542757
  2. 求哈夫曼编码就是在哈夫曼树的基础上将左子树的路径变成0,右子树的路径变成1,如下:

image-20230724110748462

a的哈夫曼编码为:011

b的哈夫曼编码为:10

c的哈夫曼编码为:00

d的哈夫曼编码为:010

e的哈夫曼编码为:11

  1. ecabcbbe
  2. WPL = 5×2 + 2×3 + 4×3 + 7×2 + 9×2

5. 并查集

image-20230722222648793

5.1 初始版本

public class unionFind{
	// 初始化并查集
	public void init(int[] nums){
		Arrays.fill(nums,-1);
	}
	// 查操作:找x所属集合,返回x所属根节点
	int find(int[] nums,int x){
		while(s[x] >= 0){
            x = s[x];
        }
        return x;
	}
	// 并操作:将两个集合合并为一体
	public void union(int[] nums,int rootX,int rootY){
		if(rootX == rootY) return;
		nums[rootY] = rootX;
	}
}

5.2 优化版本

public class unionFind{
	// 初始化并查集
	public void init(int[] nums){
		Arrays.fill(nums,-1);
	}
    
	 /**
     * 并操作:使用根节点记录树的节点数目,让小树合并到大树上
     * 该方法构造的树高不超过log2n]+1
     * @param s
     * @param x
     * @param y
     */
	public void union(int[] nums,int x,int y){
        int root1 = find(nums,x);
        int root2 = find(nums,y);
		if (root1 == root2) return;
        if(s[root2]>s[root1]){      //root2节点更少(负数)
            s[root1] += s[root2];   //将小树的根节点数目加到大树根节点上
            s[root2]  = root1;      //小树合并到大树
        }else{
            s[root2] += s[root1];
            s[root1] = root2;
        }
	}
    /**
     * 查操作:压缩路径
     * @param s
     * @param x
     * @return
     */
    int find1(int[] s,int x){
        int root = x;
        while(s[root] >= 0) root = s[root];     //循环找到根节点
        while (x != root){      //压缩路径
            int t = s[x];       //t指向x的父节点
            s[x] = root;        //x直接挂到根节点下
            x = t;
        }
        return root;
    }
}

本质上表示集合的一种逻辑关系。

image-20230722214950349

三. 🦁 总结

根据王道视频课总结的数据结构知识点,对于期末考、考研、面试的宝子有帮助哦!!!

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

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

相关文章

IDEA使用lombok实体类加上@Data注解后无法找到get和set方法

文章目录 一、问题原因二、解决方法1.File→Settings2.Plugins→搜索"lombok"→Install3.Restart IDE(重启IDEA) 一、问题原因 IDEA没有安装lombok插件 二、解决方法 1.File→Settings 2.Plugins→搜索"lombok"→Install 3.Restart…

北斗定位导航系统,北斗模块应用领域发展概况_北斗二号模块,北斗三号模块

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、北斗系统概述1.1 空间段1.2 地面控制段1.3 用户段1.4 坐标系统1.5 时间系统 二、北斗系统定位导航授时服务2.1 服务概述2.2 服务区2.3 北斗信号频段2.4 北斗…

服务器中了Locked勒索病毒怎么解决,勒索病毒解密恢复方式与防护措施

服务器是企业重要数据存储和处理的关键设备,然而,众所周知,服务器系统并非完全免受网络攻击的。其中一种常见的威胁是勒索病毒,其中一种恶名昭彰的变种是Locked勒索病毒。Locked勒索病毒采用了对称AES与非对称RSA的加密形式&#…

【C++入门到精通】C++入门 —— 引用、内联函数

目录 一、引用 1.引用的概念 2.引用的特性 3.常引用 4.引用的使用场景 ⭕做参数 ⭕做返回值 5.传值、传引用效率比较 值和引用的作为返回值类型的性能比较 6.引用和指针的区别 引用和指针的不同点 二、内联函数 1.内联函数的概念 2.内联函数的特性 3.宏与内联函数 …

RocketMQ教程-(5)-功能特性-顺序消息

顺序消息为 Apache RocketMQ 中的高级特性消息,本文为您介绍顺序消息的应用场景、功能原理、使用限制、使用方法和使用建议。 应用场景​ 在有序事件处理、撮合交易、数据实时增量同步等场景下,异构系统间需要维持强一致的状态同步,上游的事…

13.4.2 【Linux】sudo

相对于 su 需要了解新切换的使用者密码 (常常是需要 root 的密码), sudo 的执行则仅需要自己的密码即可。sudo 可以让你以其他用户的身份执行指令 (通常是使用 root 的身份来执行指令),因此并非所有人都能够…

Spring 多数据源方法级别注解实现

Spring框架提供了多种数据源管理方式,其中多数据源管理是其中之一。多数据源管理允许应用程序使用多个数据源,而不是只使用一个数据源,从而提高了应用程序的灵活性和可靠性。 多数据源管理的主要目的是让应用程序能够在不同的数据库之间切换&…

SpringCache 框架使用以及序列化和缓存过期时间问题的解决

目录 为什么使用Spring Cache 如何使用Spring Cache 1 加依赖 2 开启缓存 3 加缓存注解 序列化以及过期时间等问题 解决方案:自定义序列化方式 1.自定义序列化方式并设置白名单 2.配置并设置缓存的过期时间 为什么使用Spring Cache 缓存有诸多的好处&#x…

YOLOv5(v7.0)网络修改实践二:把单分支head改为YOLOX的双分支解耦合head(DecoupleHead)

前面研究了一下YOLOX的网络结构,在YOLOv5(tag7.0)集成了yolox的骨干网络,现在继续下一步集成YOLOX的head模块。YOLOX的head模块是双分支解耦合网络,把目标置信度的预测和目标的位置预测分成两条支路,并验证双分支解耦合头性能要优…

为什么视频画质会变差,如何提升视频画质清晰度。

在数字时代,视频已经成为我们生活中不可或缺的一部分。然而,随着视频的传输和处理过程中的多次压缩,画质损失逐渐凸显,影响了我们对影像的真实感受。为了让视频画质更加清晰、逼真,我们需要采取一些措施来保护和修复视…

设计模式大白话——观察者模式

文章目录 一、概述二、示例三、模式定义四、其他 一、概述 ​ 与其叫他观察者模式,我更愿意叫他叫 订阅-发布模式 ,这种模式在我们生活中非常常见,比如:追番了某个电视剧,当电视剧有更新的时候会第一时间通知你。当你…

Zia和ChatGPT如何协同工作?

有没有集成ChatGPT的CRM系统推荐?Zoho CRM已经正式与ChatGPT集成。下面我们将从使用场景、使用价值和使用范围等方面切入讲述CRMAI的应用和作用。 Zia和ChatGPT如何协同工作? Zia和ChatGPT是不同的人工智能模型,在CRM中呈现出共生的关系。 …

荧光信号采集的2种方法

本文介绍荧光信号采集的2种方法。 荧光信号采集是生化类医疗设备(PCR,荧光免疫分析仪)常用的功能,针对不同类型的激发光和发射光采用的荧光信号采集方法也不一样。 1.基本概念 1)发光原理 当待测物质受到外接某一波长的入射光…

生物信息学_玉泉路_课堂笔记_02 第二章 序列比对和序列数据库搜索

🍅 课程:生物信息学_玉泉路_课堂笔记 中科院_2022秋季课 第一学期 🍅 个人笔记使用 🍅 2023/7/5 一、上周回顾 二、生物信息学的展望 —— 精准医学的发展 生物信息学的开拓者 三、双序列比对的常用算法 序列比对的需求 使用 b…

基于包围框回归的目标检测网络原理及Tensorflow实现

对象检测是对图像内的对象进行分类和定位。 换句话说,它是图像分类和对象定位的结合。 构建用于图像分类的机器学习模型更简单,我在我的一篇文章中对此进行了描述。 然而,图像分类器无法准确判断对象在图像内的位置。 为了实现这一目标&#…

opencv对相机进行畸变矫正,及从矫正后的图像坐标反求原来的对应坐标

1.背景 目前有个项目,需要用到热成像相机。但是这个热成像相机它的畸变比较厉害,因此需要用标定板进行标定,从而消除镜头畸变。 同时需要实现用户用鼠标点击矫正后的画面后,显示用户点击位置的像素所代表的温度。 2.难点 消除镜…

1-1 AUTOSAR是什么?

目录 一、AUTOSAR组织 二、AUTOSAR的版本 三、AUTOSAR的理念 四、AUTOSAR的动机 五、AUTOSAR目标 六、AUTOSAR的优势 6.1 商业优势 6.2 技术优势 一、AUTOSAR组织 AUTOSAR(Automotive Open System Architecture)是一个全球性的汽车行业标准化组织…

【流形和流形空间(姿态)】

定义 流形(Manifold)是一种广义的曲面概念,用于描述局部上类似于欧几里德空间的空间。简而言之,流形是一个局部与欧几里德空间同胚(homeomorphic)的空间,但并不一定是全局上同胚的。&#xff0…

Springboot项目打包war配置详解

Springboot项目打包war配置详解 1. 排除内置tomcat依赖2. 添加servlet依赖3. 修改打包方式4. 修改主启动类5. 完整pom.xml6. 效果图 1. 排除内置tomcat依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

Keil系列教程08_Configuration(二)

1写在前面 本文接着上一篇文章《Keil系列教程07_Configuration&#xff08;一&#xff09;》讲述的工程目标选项的后三项配置&#xff1a;Shortcut Keys快捷键、Text Completion代码完形、Other其他。 这后面三部分内容在该系列教程其它也会牵涉&#xff0c;也是一些常用、重要…