n4.树(上)

devtools/2024/9/23 22:41:39/

一、树与树的表示

1.查找

在这里插入图片描述

静态查找,查找的对象集合本身不发生改变,例如查字典;动态查找,查找的对象集合本身是动态变化的。

顺序查找

在这里插入图片描述

将数据储存在数组里,按照顺序进行查找。此外需要一个结构指针Tbl,它的Data域是数组中元素的个数;指针域指向这个数组。需要存n个数据,就把数组大小设为a[n+1]。因为要设置一个哨兵a[0] = K,用来终止循环判断是否查找到K,a[1]到a[n]用来储存数据。

struct LNode{int length;int Arr[MaxSize];	
};
typedef struct LNode* List;//结构指针
Search(int K;List Tbl)//假设要找的元素是K
{List->Arr[0] = K;for(int i = List->Tbl;List->Arr[i] != K;i--);//注意是从索引大向着索引小的方向循环遍历查找Kreturn i;
}

没有哨兵的话,循环结束,意味着找到了K或者超出了数组的边界。for(int i = List->length; List->Arr[i] != K && i>=0;i--)这样就会复杂些。
哨兵的作用就是我们再循环的时候不需要每次去判断他的下标,少写一个判断分支。而且只要循环结束,可以马上知道是否有元素K。返回0表示数组中没有元素K;返回其他的表示查找成功
注意循环是从大索引向小索引查找。
在这里插入图片描述
这样的查找方法效率不高

二分查找

在这里插入图片描述

  • 二分查找可以实现的前提
    1数据存放在数组里面
    2数据在数组中是有序排放的,降序或者升序。
  • 举例:
    在这里插入图片描述

因为mid = 100 < 444,所以就可以确定444在右半部分。所以舍弃左半部分,对右半部分重复进行操作。
在这里插入图片描述

代码

从a[0]开始储存数据,Search()函数查找K,并返回K所在的位置下标;Sort函数进行冒泡排序;

void Sort(int a[], int length);
int Search(int a[], int length, int K);
int main()
{int a[] = { 9,5,2,4,3, };int length = sizeof(a) / sizeof(a[0]);Sort(a, length);printf("排序之后的数组:\n");for (int i = 0; i < length; i++){printf("%d ", a[i]);}printf("\n");int four = Search(a, length, 4);int non = Search(a, length, 7);int nine = Search(a, length, 9);printf("4的下标在%d\n", four);printf("9的下标在%d\n", nine);printf("7的下标在%d\n", non);return 0;}
void Sort(int a[],int length)//length 链表的长度
//由于冒泡排序的特殊性,无法对部分元素进行排序,要排就全都排
{int i, j;for (i = 0; i < length - 1; i++){//第一次层循环控制冒泡排序 冒泡的轮数//length个数,需要冒泡length-1次,每次冒泡就会完成对一个数的排序for (j = 0; j < length - 1 - i; j++){//第二次循环控制本轮冒泡需要比较的次数//这里i表示已经完成排序的元素的个数,每轮需要比较的元素个数依次减小;if (a[j] > a[j + 1]){//交换两个元素的值int temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}//完成升序排序}}
}
int Search(int a[], int length, int K)
{//二分查找的函数int left = 0,right = length -1;while (left <= right)//判定条件:不越界{int middle = (left + right) / 2;if (K > a[middle])//因为是升序排序,说明在右半部分,变left{left = middle + 1;}else if (K < a[middle]){right = middle - 1;}elsereturn middle;}return -1;}

时间复杂度:O(logN)

二分查找的判定树

11个元素,1到11进行查找,使用判定树进行模拟。第一次查找肯定是将K与6进行比较,判断是在左半部分还是在右半部分,依次进行下去…
第一次查找可找到6;第二次查找可找到3,9;第三次查找可找到1,4,7,10…
在这里插入图片描述

  • 这个树一共有四层(从上到下),如果要查找4,那么久需要查找3次,因为4在第三层;
  • ASL(平均寻找次数) = (需要找4次的数字个数 + 需要找3次的数字个数 + 需要找2次的数字个数+…)/ 数字总个数;
    使用层次化的结构储存数据:查找树的形式,原理类似二分查找,使得查找过程更加方便,当在树中查找节点、删除节点的时候,会比数组方便得多,可以更好地处理动态查找问题。

2.树的定义和术语

定义

在这里插入图片描述

类似递归的思路,一个树有多个子树组成,每个树都有根Root…

  • 每个子树之间互不相交
  • 除了根节点之外,每个节点有且只有一个父节点
  • 一棵有N个节点的树有N-1条边。因为除了根节点A,每个节点都只有向上的一条边。
  • 树是保证节点联通的边最少的一种连接方式。

术语

在这里插入图片描述

例如,右图中的树:

  • 节点的度为3,因为根节点A有三个子树;
  • 树的度为3,看最多的子树数目:A和D最大度数;
  • 叶节点,即没有子树的结点:FLH…
    在这里插入图片描述

右图中树的深度为4;

3.树的表示

使用数组实现起来相对困难;如果使用链表表示树,那么就需要每个节点的指针个数都是相同的,会造成较大的空间上的浪费。
在这里插入图片描述

那么就可以使用儿子兄弟表示法
在这里插入图片描述

将他旋转45度,可以看成一个树,每个节点都有两个指针,一个指向左边,一个指向右边。这种树叫做二叉树,度为2的一种数。
在这里插入图片描述

一般的树就可以使用二叉树链表的形式来实现。

二、二叉树及储存结构

1.二叉树的定义及性质

二叉树的定义

在这里插入图片描述

  • 二叉树的左子树和右子树两不相交,二叉树可以是空树,可以只有一个结点,可以只有左子树,可以只有右子树,可以有左右子树。注意二叉树是一种度为2的数,子树有左右顺序之分。而一般的度为2的树,子树是没有左右之分的。

特殊二叉树

在这里插入图片描述

斜二叉树,就是单链表;
完美二叉树(满二叉树),对称完美?

  • 完全二叉树
    在这里插入图片描述
    在这里插入图片描述

使用编号的检查

二叉树的性质

在这里插入图片描述
最大节点的情况:完美二叉树
最大节点总数,就是k层所有的节点求和

在这里插入图片描述

n0表示叶节点的个数;n1表示只有一个儿子的结点个数;n2表示有两个儿子的结点。关系为n0 = n2 + 1。证明方法:使用两种对总数边的求法
在这里插入图片描述

二叉树的抽象数据类型定义

在这里插入图片描述

其中对二叉树的遍历是最基本的操作。常见的遍历方法有四种。

2.二叉树的存储结构

顺序储存结构

对于完全二叉树(比较适合):

在这里插入图片描述

使用数组来连续存储完全二叉树,即使用对结点编号的方式来对应数组元素的下标
a[n+1] 表示可以储存序号从1 到 n,已知任何一个结点,都可以进行访问操作:

  • 查找父节点:a[i] 的父节点为 a[i/2] ,注意i/2取整
  • 左孩子:a[i] 的左孩子是a[2i];
  • 右孩子: a[i] 的右孩子是a[2i + 1];
  • 如果下标索引超出n-1,那么此节点就没有所查找的结点。
对于一般的二叉树(空间浪费):


索引访问的对应关系仍然适用!但是会造成空间浪费。比如这个例子,只有五个节点有数据,却需要使用13个数组空间来储存。

链式储存

在这里插入图片描述

节点不存在的情况使用NULL来表示。


http://www.ppmy.cn/devtools/8824.html

相关文章

mysql基础5——设置主键

业务字段尽量不要用做主键 删除主键&#xff0c;只是主键被删除&#xff0c;字段还存在 alter table demo.membermaster drop primary key; 添加一个字段设置为主键并给主键添加自增约束 alter table demo.membermaster add column id int primary key auto_increment; 自增…

个人电脑信息安全注意事项

个人电脑信息安全注意事项 一、密码安全&#xff1a; 设置复杂且独特的密码&#xff0c;避免使用容易猜测或常见的密码。 定期更换密码&#xff0c;特别是在重要账户或应用上。 不要在多个账户上重复使用相同的密码。 使用密码管理工具来安全地存储和访问密码。 二、软件安…

npm config set registry切换npm镜像源

要切换 npm 镜像源&#xff0c;可以使用 npm config set registry 命令。以下是切换到官方的 npm 镜像源的步骤&#xff1a; 查看当前 npm 镜像源&#xff1a; npm config get registry如果当前的镜像源不是官方的 npm 镜像源&#xff08;https://registry.npmjs.org/&#xff…

网络靶场实战-Qiling Fuzz实例分析

背景 在上一小节中&#xff0c;介绍了qiling框架的背景和基础使用&#xff0c;并以相关的CTF和qilinglab实例进行练习加深对qiling框架的使用&#xff0c;后续并简单介绍了qiling fuzz的功能。 在这一小节&#xff0c;我们将对qiling fuzz iot设备进行测试以及以实例的方式对…

MultiCD工具:创建一个多引导Linux USB驱动器

众所周知&#xff0c;拥有一个可安装多个可用操作系统的 CD 或 USB 驱动器在各种情况下都非常有用。无论是为了快速测试或调试某些内容&#xff0c;还是只是重新安装笔记本电脑或 PC 的操作系统&#xff0c;这都可以为你节省大量时间。 在本文中&#xff0c;将介绍如何使用名为…

人人可拥有刘强东同款数字人分身!

每个人都可以拥有东哥同款数字人分身直播间进行直播带货&#xff0c;怎样克隆自己的数字人形象&#xff1f; 青否数字人克隆源码的克隆效果媲美真人&#xff1a; 仅需将真人录制的2-6分钟视频上传至克隆端后台&#xff0c;系统便会自动启动自动克隆。3-5小时后&#xff0c;即可…

十三、系统高级类和异常处理

掌握如下系统高级类的属性、方法和它的应用 1、Object类 1)系统高级类-Object类 java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入。 Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类。 Object类是Java中唯一没有父类的类。…

HTML5声明与编码设置

HTML5声明与编码设置 HTML5的DOCTYPE声明 <!DOCTYPE html> 语言的声明方式 <html lang"zh-CN"> lang属性设置为zh-CN&#xff0c;表示文件内容使用简体中文 网页编码的声明 <meta charset"GB2312"> <meta charset"UTF-8…