数据结构之动态查找表

news2024/10/7 10:25:39

数据结构之动态查找表

  • 1、二叉排序树
    • 1.1、二排序树的定义
    • 1.2、二叉排序树的查找过程
    • 1.3、在二叉排序树中插入结点的操作
    • 1.4、在二叉排序树中删除结点的操作
  • 2、平衡二叉树
    • 2.1、平衡二叉树上的插入操作
    • 2.2、平衡二叉树上的删除操作
  • 3、B_树

  数据结构是程序设计的重要基础,它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所涉及的数据选择适当的逻辑结构、存储结构及其相应的操作方法,为提高利用计算机解决问题的效率服务。
  动态查找表的特点是表结构本身是在查找过程中动态生成的,即对于给定值 key,若表中存在关键字等于 key 的记录,则查找成功返回;否则插入关键字为 key 的记录。

1、二叉排序树

1.1、二排序树的定义

  二叉排序树又称二叉查找树,它或者是一棵空树,或者是具有以下性质的二叉树。
  (1)若它的左子树非空,则左子树上所有结点的值均小于根结点的值。
  (2)若它的右子树非空,则右子树上所有结点的值均大于根结点的值。
  (3)左、右子树本身是二叉排序树。
  下图为一棵二叉排序树。
在这里插入图片描述

1.2、二叉排序树的查找过程

  因为二叉排序树的左子树上所有结点的关键字均小于根结点的关键字,右子树上所有结点的关键字均大于根结点的关键字,所以在二叉排序树上进行查找的过程为: 二叉排序树非空时,将给定值与根结点的关键字值相比较,若相等,则查找成功;若不相等,则当根结点的关键字值大于给定值时,下一步到根的左子树中进行查找,否则到根的右子树中进行查找。若查找成功,则查找过程是走了一条从树根到所找到结点的路径;否则,查找过程终止于一棵空的子树。
  设二叉排序树采用二叉链表存储,结点的类型定义如下:

typedef struct Tnode{
	int data;						/*结点的关键字值*/
	struct Tnode *lchild,*rchild;	/*指向左、右子树的指针*/
}BSTnode,*BSTree;

  【函数】二叉排序树的查找算法。

BSTree SearchBST(BSTree root, int key, BSTree *father)
/*在root 指向根的二叉排序树中查找键值为 key 的结点*/
/*若找到,返回该结点的指针;否则返回空指针 NULL*/
{
	BSTree p = root; 
	*father = NULL;
	while (p && p->data!=key){
		*father = p;
		if( key < p->data ) p = p->lchild;
		else p = p->rchild;
	}/*while*/
	return p;
}/*SearchBST*/

1.3、在二叉排序树中插入结点的操作

  二叉排序树是通过依次输入数据元素并把它们插入到二叉树的适当位置构造起来的,具体的过程是:每读入一个元素,建立一个新结点。若二叉排序树非空,则将新结点的值与根结点的值相比较,如果小于根结点的值,则插入到左子树中,否则插入到右子树中;若二叉排序树为空,则新结点作为二叉排序树的根结点。设关键字序列为{46,25,54,13,29,91},则整个二叉排序树的构造过程如下图 所示。
在这里插入图片描述

  【函数】二叉排序树的插入算法。

int InsertBST(BSTree *root, int newkey)
/*在*root 指向根的二叉排序树中插入一个键值为 newkey 的结点,插入成功则返回0,否则返回-1*/
{
	BSTree s,p,f;
	s =(BSTree)malloc(sizeof(BSTnode));
	if (!s) return -1;
	s->data = newkey; 
	s->lchild = NULL;
	s->rchild = NULL;
	p = SearchBST(*root, newkey, &f);		/*寻找插入位置*/
	if(p) return -1;						/*键值为 newkey 的结点已在树中,不再插入*/
	if(!f) *root= s;						/*若为空树,键值为newkey 的结点为树根*/
	else if (newkey < f->data) 				/*作为父结点的左孩子插入*/
		f->lchild = s;
	else f->rchild = s;						/*作为父结点的右孩子插入*/
	return 0;
}/*InsertBST*/

  从上面的插入过程还可以看到,每次插入的新结点都是二叉排序树上新的叶子结点,因此插入结点时不必移动其他结点,仅需改动某个结点的孩子指针。这就相当于在一个有序序列上插入一个记录而不需要移动其他记录。这表明在二叉排序树进行查找具有类似于折半查找的特性,二叉排序树可采用链表存储结构,因此是动态查找表的一种适宜表示。
  另外,由于一棵二叉排序树的形态完全由输入序列决定,所以在输入序列已经有序的情况下,所构造的二叉排序树是一棵单枝树。例如,对于关键字序列 (12,18,23,45,60),建立的二叉排序树如下图所示,这种情况下的查找效率与顺序查找的效率相同。
在这里插入图片描述

1.4、在二叉排序树中删除结点的操作

  在二叉排序树中删除一个结点,不能把以该结点为根的子树都删除,只能删除这个结点并仍旧保持二叉排序树的特性。也就是说,在二叉排序树上删除一个结点相当于在有序序列中删除一个元素。
  假设要在二叉排序树种删除结点 *p(p 指向被删除结点),*f 为其双亲结点,则该操作可分为3 种情况:结点*p 为叶子结点; 结点*p 只有左子树或者只有右子树;结点*p 的左子树、右子树均存在。
  (1)若结点 *p 为叶子结点且 *p 不是根结点,即 p->lchild 及 p->rchild 均为空,则由于删去叶子结点后不破坏整棵树的结构,因此只需修改 *p 的双亲结点 *f 的相应指针即可。
    f->lchild(或 f->rchild)= NULL;
  若结点 *p 只有左子树或者只有右子树且 *p 不是根结点,此时只要将 *p 的左子树或右子树接成其双亲结点 *f的左子树(或右子树),即令
    f->lchild (或 f->rchild)= p->lchild;
  或
    f>lchild(或 f>rchild) = p->rchild:
  (3)若 *p 结点的左、右子树均不空,则删除 *p 结点时应将其左子树、右子树连接到适当的位置,并保持二叉排序树的特性。可采用以下两种方法进行处理:一是令 *p 的左子树为 *f的左子树(若 *p 不是根结点且 *p 是 *f的左子树,否则为右子树),而将 *p 的右子树下接到中序遍历时 *p 的直接前驱结点 *s ( *s 结点是 *p 的左子树中最右下方的结点) 的右孩子指针上;是用 *p 的中序直接前驱(或后继)结点 *s 代替 *p 结点,然后删除 *s 结点,如下图所示
在这里插入图片描述

  从二叉排序树的定义可知,中序遍历二叉排序树可得到一个关键字有序的序列。这也说明,一个无序序列可以通过构造一棵二叉排序树而得到一个有序序列,构造二叉排序树的过程就是对无序序列进行排序的过程。

2、平衡二叉树

  平衡二叉树又称为 AVL 树,它或者是一棵空树,或者是具有下列性质的二叉树。它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度之差的绝对值不超过 1。若将二叉树结点的平衡因子(Balance Factor,BF) 定义为该结点左子树的高度减去其右子树的高度,则平衡二叉树上所有结点的平衡因子只可能是-1、0 和 1。只要树上有一个结点的平衡因子的绝对值大于1,则该二又树就是不平衡的。
  分析二叉排序树的查找过程可知,只有在树的形态比较均匀的情况下,查找效率才能达到最佳。因此,希望在构造二叉排序树的过程中,保持其为一棵平衡二叉树。
  使二叉排序树保持平衡的基本思想是: 每当在二叉排序树中插入一个结点时,首先检查是否因插入破坏了平衡。若是,则找出其中的最小不平衡二叉树,在保持二叉排序树特性的情况下,调整最小不平衡子树中结点之间的关系,以达到新的平衡。所谓最小不平衡子树,是指离插入结点最近且以平衡因子的绝对值大于1 的结点作为根的子树。

2.1、平衡二叉树上的插入操作

  一般情况下,假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a,也就是说,a 所指结点是离插入结点最近且平衡因子的绝对值超过1的祖先结点,那么,失去平衡后进行调整的规律可归纳为以下4种情况。
  (1)LL型单向右旋平衡处理。如下图所示,由于在 *a(即结点A)的左子树的左子树上插入新结点,使 *a 的平衡因子由1增至2,导致以*a 为根的子树失去平衡,因此需进行一次向右的顺时针旋转操作。
在这里插入图片描述

  (2)RR型单向左旋平衡处理。如下图所示,由于在 *a(即结点A)的右子树的右子树上插入新结点,使 *a 的平衡因子由 -1变为 -2,导致以 *a 为根的子树失去平衡,因此需进行一次向左的逆时针旋转操作。
在这里插入图片描述

  (3)LR型先左后右双向旋转平衡处理。如下图所示,由于在 *a(即结点A)的左子树的右子树上插入新结点,使 *a 的平衡因子由 1 增至2,导致以 *a 为根结点的子树失去平衡,因此需进行两次旋转(先左旋后右旋)操作。
在这里插入图片描述

  (4)RL型先右后左双向旋转平衡处理。如下图所示,由于在 *a(即结点A)的右子树的左子树上插入新结点,使 *a的平衡因子由 -1变为 -2,导致以 *a为根结点的子树失去平衡,因此需进行两次旋转(先右旋后左旋)操作。
在这里插入图片描述

2.2、平衡二叉树上的删除操作

  在平衡二叉树上进行删除操作比插入操作更复杂。若待删结点的两个子树都不为空,就用该结点左子树上的中序遍历的最后一个结点(或其右子树上的第一个结点)替换该结点,将情况转化为待删除的结点只有一个子树后再进行处理。当一个结点被删除后,从被删结点到树根的路径上所有结点的平衡因子都需要更新。对于每一个位于该路径上的平衡因子为 ±2 的结点来说,都要进行平衡处理。

3、B_树

  一棵m阶的B_树,或为空树,或为满足下列特性的m叉树。
  (1)树中每个结点最多有m棵子树。
  (2)若根结点不是叶子结点,则最少有两棵子树。
  (3)除根之外的所有非终端结点最少有 m 2 \frac m2 2m棵子树。
  (4)所有的非终端结点中包含下列数据信息
( n , A 0 , K 1 , A 1 , K 2 , A 2 , . . . , K n , A n ) (n,A_0,K_1,A_1,K_2,A_2,...,K_n,A_n) (n,A0,K1,A1,K2,A2,...,Kn,An)
其中,Ki(i=1,2,…,n)为关键字,且Ki<Ki+1(i=1,2,…,n-1); Ai(i=0,1,…,n)为指向子树根结点的指针,且指针 Ai-1 所指子树中所有结点的关键字均小于 Ki(i=1,2,…,n),An所指子树中所有结点的关键字均大于Kn,n 为结点中关键字的个数且满足 { m 2 − 1 ≤ n ≤ m − 1 } {\huge\{}\frac m2 -1≤n≤m-1\huge\} {2m1nm1}
  (5)所有的叶子结点都出现在同一层次上,并且不带信息(可以看作是外部结点或查找失败的结点,实际上这些结点不存在,指向这些结点的指针为空)。
  一棵4阶的B树如下图所示。
在这里插入图片描述

  由 B树的定义可知,在 B树上进行查找的过程是:首先在根结点所包含的关键字中查找给定的关键字,若找到则成功返回;否则确定待查找的关键字所在的子树并继续进行查找,直到查找虚功或查找失败(指针为空) 时为止。
  B树上的插入和删除运算较为复杂,因为要保证运算后结点中关键字的个数大子等于 m 2 − 1 \frac m2-1 2m1,因此涉及结点的“分裂”及“合并”问题。
  在B树中插入一个关键字时,不是在树中增加一个叶子结点,而是首先在低层的某个非终端结点中添加一个关键字,若该结点中关键字的个数不超过 m-1,则完成插入;否则,要进行结点的“分裂”处理。所谓“分裂”,就是把结点中处于中间位置上的关键字取出来插入到其父结点中,并以该关键字为分界线,把原结点分成两个结点。“分裂”过程可能会一直持续到树根。
  同样,在 B_树中删除一个结点时,首先找到关键字所在的结点,若该结点在含有信息的最后一层,且其中关键字的数目不少于 m 2 − 1 \frac m2-1 2m1,则完成删除;否则需进行结点的“合并”运算。若待删除的关键字所在的结点不在含有信息的最后一层,则将该关键字用其在 B 树中的后继替代,然后删除其后继元素,即将需要处理的情况统一转化为在含有信息的最后一层再进行删除运算。

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

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

相关文章

js新增的操作元素类名的方法

Element.classList是一个只读属性&#xff0c;返回一个元素 class 属性的动态 DOMTokenList 集合。这可以用于操作 class 集合。 尽管 classList 属性自身是只读的&#xff0c;但是你可以使用 add()、remove()、replace() 和 toggle() 方法修改其关联的 DOMTokenList。 兼容性…

移动机器人激光SLAM导航(二):运动控制与传感器篇

参考引用 机器人工匠阿杰wpr_simulation 1. 机器人运动控制 1.1 测试环境安装 wpr_simulation 安装$ mkdir -p catkin_ws/src $ cd catkin_ws/src $ git clone https://github.com/6-robot/wpr_simulation.git $ cd wpr_simulation/scripts/ $ ./install_for_melodic.sh # 自…

【2023地理设计组一等奖】基于机器学习的地下水仿真与时空分析

作品介绍 1 设计思想 1.1 作品背景 华北平原是我国最重要的粮棉产地之一,然而近年来农业的低效用水以及过度压采正逐步加剧其地下水资源的紧张性,为经济可持续发展带来重大风险。而地下水动态变化与人为干预、全球气候波动呈现出高度相关性,因此,地下水的仿真模拟对保障粮…

使用阿里云的IDaaS实现知行之桥EDI系统的单点登录

&#xff0c;在开始测试之前&#xff0c;需要确定用哪个信息作为“登陆用户的ID字段”。 这个字段用来在完成SSO登陆之后&#xff0c;用哪个信息将阿里云IDaaS的用户和知行之桥EDI系统的用户做对应。这里我们使用了 phonenumber 这个自定义属性。需要在阿里云做如下配置&#x…

Qt实现类似ToDesk顶层窗口 不规则按钮

先看效果&#xff1a; 在进行多进程开发时&#xff0c;可能会遇到需要进行全局弹窗的需求。 因为平时会使用ToDesk进行远程桌面控制&#xff0c;在电脑被控时&#xff0c;ToDesk会在右下角进行一个顶层窗口的提示&#xff0c;效果如下&#xff1a; 其实要实现顶层窗口&#xf…

openssl3.2 - 官方demo学习 - pkcs12 - pkwrite.c

文章目录 openssl3.2 - 官方demo学习 - pkcs12 - pkwrite.c概述学到的知识点笔记PEM证书可以拼接实验 pkcs12 - pkwrite.c用win10的证书管理器安装P12证书是成功的END openssl3.2 - 官方demo学习 - pkcs12 - pkwrite.c 概述 openssl3.2 - 官方demo学习 - 索引贴 上次PKCS12的…

【Qt】Json在Qt中的使用

Json JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;广泛用于互联网应用程序之间的数据传输。JSON基于JavaScript中的对象语法&#xff0c;但它是独立于语言的&#xff0c;因此在许多编程语言中都有对JSON的解析和生成支持。…

[opencvsharp]C#基于Fast算法实现角点检测

角点检测算法有很多&#xff0c;比如Harris角点检测、Shi-Tomas算法、sift算法、SURF算法、ORB算法、BRIEF算法、Fast算法等&#xff0c;今天我们使用C#的opencvsharp库实现Fast角点检测 【算法介绍】 fast算法 Fast(全称Features from accelerated segment test)是一种用于角…

集合问题(并查集)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例1&#xff1a; 输入 4 5 9 2 3 4 5 输出 YES 0 0 1 1 样例2&#xff1a; 输入 3 3 4 1 2 4 输出 NO 思路&#xff1a; 这道题关键点在于。 当集合中有一个元素均存在于集合 A 和集合 B 的时…

(杂项笔记)腾讯文档设置隔行换色

文档小技巧 一、在表格工具栏中选择“数据”栏二、选择新建条件格式三、进行以下设置1. 应用范围2. 条件设置3. 这是表格颜色 四、样例展示1. 隔行换色2. 隔3行换色 最近在使用某家的文档进行多人协同办公&#xff0c;遇到的一些小技巧&#xff0c;在这里分享给大家&#xff1b…

无广告iOS获取设备UDID 简单方便快捷

ps&#xff1a; 为啥不用蒲公英了&#xff0c;就是因为有广告了&#xff0c;获取个UDID还安装游戏&#xff0c;真恶心?&#xff0c;所以找了新的获取UDID都方法&#xff0c;网页直接获取就可以&#xff0c;不会安装软件。 UDID 是一种 iOS 设备的特殊识别码。除序号之外&…

Java多线程--解决单例模式中的懒汉式的线程安全问题

文章目录 一、单例设计模式的线程安全问题&#xff08;1&#xff09;饿汉式没有线程安全问题&#xff08;2&#xff09;懒汉式线程安全问题1、案例2、方式1-同步方法3、方式2-同步代码块4、优化 二、代码&#xff08;1&#xff09;实现线程安全的懒汉式&#xff08;2&#xff0…

【力扣白嫖日记】SQL

前言 练习SQL语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1387.使用唯一标识码替代员工ID 表&#xff1a;Employees 列名类型idintnamevarchar 在 SQL 中&#xff0c…

k8s安装dashboard报错CrashLoopBackOff

报错信息 使用kubectl get pods -A查看集群&#xff0c;出现错误&#xff1a; kubernetes-dashboard kubernetes-dashboard-xxxxxxxxxx6-2qrst 0/1 CrashLoopBackOff 6 15m查看日志后&#xff0c;发现原因&#xff1a; panic: Get "https://10…

Pandas 数据结构 – Pandas CSV 文件

Pandas CSV 文件 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff0c;有时也称为字符分隔值&#xff0c;因为分隔字符也可以不是逗号&#xff09;&#xff0c;其文件以纯文本形式存储表格数据&#xff08;数字和文本&#xff09;。 CSV 是一种通用的、…

【IC设计】Windows下基于IDEA的Chisel环境安装教程(图文并茂)

Chisel环境安装教程 第一步 安装jdk&#xff0c;配置环境变量第二步 安装sbt&#xff0c;不用配置环境变量第三步 安装idea社区版第四步 离线安装scala的idea插件第五步 配置sbt换源1.切换目录2.创建repositories文件3.配置sbtconfig.txt文件 第六步 使用chisel-tutorial工程运…

Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin

Android矩阵setRectToRect裁剪Bitmap原图Matrix放大&#xff0c;mapRect标记中心区域&#xff0c;Kotlin import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.Matrix impo…

数学知识第八期 组合数全集

前言&#xff1a;组合数在高中大家应该都学过&#xff0c;也是一个重要的数学知识&#xff0c;希望大家能够完全掌握 一、组合数基本知识 定义&#xff1a; 组合是数学的重要概念之一。从 n 个不同元素中每次取出 m 个不同元素 &#xff0c;不管其顺序合成一组&#xff0c;称…

YIA主题如何关闭新版本升级提示?WordPress主题怎么取消升级提醒?

前两天YIA主题发布了升级到2.8版本&#xff0c;新增了一些功能&#xff0c;优化调整修复了一些功能&#xff0c;但是这些功能调整幅度不大&#xff0c;加上boke112百科使用的YIA主题已经进行了很多方面的个性化修改&#xff0c;所以就懒得升级了&#xff0c;但是每次进入WordPr…

C++——数据类型

C——数据类型 1.基本变量类型 C 基本数据类型整理成表格。以下是一个表格&#xff0c;展示了不同的基本数据类型及其一般用途和大小范围&#xff1a;和C语言类似。 2.宽字符的用法 #include <iostream> #include <locale> #include <wchar.h> int main…