【数据结构】7.2 线性表的查找

news2025/2/28 5:22:23

7.2.1 顺序查找(线性查找)

应用范围

  • 顺序表或线性链表表示的静态查找表
  • 表内元素之间可以无序

数据元素类型定义

  • 数据表可能有多个数据域的值,比如成绩表中有姓名、成绩、总分等。
  • 所以用结构类型来表示要存储的数据元素的类型。
typedef struct
{
		Keytype key;//关键字域
		InfoType otherinfo;//其他域

}ElemType;

顺序表的定义

//顺序表结构类型定义
typedef struct
{
		ElemType* R;//存储空间基地址
		int length;//记录当前表用了多少个数据元素

}SSTable;//Sequential Search Table
SSTable St;//定义顺序表 ST

顺序查找算法

顺序查找

  • 在顺序表 ST 中查找值为 key 的数据元素。
  • 例如:查找 13:找到,返回下标 5。查找 60:未找到,返回 NULL。
    • 在此假设元素从 ST.R[1] 开始顺序向后存放,ST.R[0] 闲置不用,
    • 查找时从表的最后开始比较,如下面的算法所示。

在这里插入图片描述

算法描述

//在顺序表 ST 中顺序查找其关键字等于 key 的数据元素。
//若找到,则函数值为该元素在表中的位置(下标),反之返回0.

int Search_Seq(SSTable St,KeyType key)
{
		for(i = St.length;i>=1;i--)//从表的最后开始往前找,i指向数组最后一个元素
		{
				if(key == ST.R[i].key)
				{
						return i;//返回下标
				}
		}

		return 0;//循环完了还没找到说明里面没有要找的元素。
}
  • 这种算法每进行一次循环都要进行两个比较,能否改进?
  • 一次是看看查找的值是不是关键字的值,一次是判断 i 是否越界了。
  • 这种算法用起来稍微麻烦了点,所以这时候就轮到哨兵出击了。

设置监视哨的顺序查找

改进:把待查找关键字 key 存入表头(哨兵监视哨),从后往前逐个比较,可以免去查找过程中每一步都要检查是否检查完毕,加快速度。

  • 假设现在要找的值时 60 ,将要找的值存进0号位置(监视哨)。
  • 在找 60 的时候就不用考虑是否越界了。
  • 一直从后往前找,如果在 0 号位置找到了 60,直接返回下标 0 。也就说明在 1-11号位置没有找到60。

在这里插入图片描述

算法描述

  • 当 ST.length 比较大时,此改进能够使进行一次查找所需要的平均时间几乎减少一半
//在顺序表 ST 中顺序查找其关键字等于 key 的数据元素。
//若找到,则函数值为该元素在表中的下标位置,反之返回0

int Search_Seq(SSTable St,KeyType key)
{
		ST.R[0].key = key;//哨兵,将关键字的值放到下标为0的位置

		for(i = St.length;ST.R[i] != key;i--); //别忘了 for 后面的分号,忘了就完犊子了
		return i;
}

顺序查找算法分析

设置监视哨的顺序查找】:时间效率分析

比较次数与 key 的位置有关:

  • 查找第 i 个元素,需要边角 n- i + 1 次。
  • 查找失败时,需要比较 n + 1 次。

在这里插入图片描述

顺序查找的性能分析

  • 时间复杂度O(n)
    • 查找成功时的平均查找长度,设表中各记录查找概率相等。
      在这里插入图片描述
  • 空间复杂度O(1) 需要一个额外的辅助空间(哨兵)。

讨论

  1. 记录的查找概率不相等时如何提高查找效率?
    • 查找表存储记录原则 —— 按查找概率高低存储:
      • 查找概率越高,比较次数越少,放在比较靠后的位置。
      • 查找概率越低,比较次数越多,放在比较靠前的位置。
  2. 记录的查找概率事先不知道时该如何提高查找效率?
    • 方法 —— 按查找概率动态调整记录顺序:
      • 在每个记录中设置一个访问频度域;
      • 始终保持记录按非递增有序的次序排列;
      • 每次查找后均将刚查到的记录直接移动到表头。

顺序查找的特点

  • 优点:算法简单,逻辑次序无要求,且不同存储结构均适用(顺序/链式存储均可)。
  • 缺点:平均查找长度 ASL 太长,时间效率很低。

在这里插入图片描述

7.2.2 折半查找(二分或对分查找)

  • 二分查找:每次将待查记录所在区间缩小一半。只对已经排序的数据有效。

查找过程

在这里插入图片描述
当前数组内的数据元素是按照升序排序的。

  1. 设置一个查找区间初始值,low 指向第一个元素,high 指向最后一个元素。
  2. 当 low <= high 时,循环执行以下操作:
    • 设一个 mid 为 low 和 high 的中间值:mid = (low + high) / 2,当前这个数组的 mid 是 下标 6的元素56。
    • 直接将要找的这个关键字的值 21 和 和中间位置的这个值比较一下,发现 21 < 56,说明这个值一定在 mid 的左边。要将查找范围更新到 mid 左边。
    • 则将新的 high 更新为:key < mid 则:high = mid - 1,因为中间位置也比较过来,不是这家伙。

在这里插入图片描述
在这里插入图片描述

  • 继续拿 mid 的值和 21 比较,发现 19 < 21,说明待查找的值在 mid 的右边,将 low 更新,key > mid 则: low = mid +1
  • 然后再去找中间位置,low是4 high 是5,min的值就是4。

在这里插入图片描述

  • 拿 key 的值 21 和 mid 的值比较,发现 mid = key 则:return mid

如果要找的值不在数组中

在这里插入图片描述
在这里插入图片描述

  • 查找到最后 low 会大于 high 上下限交换了,此时说明数组中没有俺们要找的数。
  • high < low,结束

折半查找算法

非递归算法

  • 设表长为 n ,low、high 和 mid 分别指向待查元素所在区间的上限、下限和中点,令 key 为给定的要查找的值:
  • 初始时,令 low = 1,high = n,mid = (low + high) /2
  • 让 key 与 mid 指向的记录比较:
    • 若 key == R[mid].key,则查找成功。
    • 若 key < R[mid].key,则 high = mid + 1。
    • 若 key > R[mid].key,则 low = mid + 1。
int serch_Bin(SSTable ST,KeyType key)
{
		low = 1;high = ST.length;//置查找区间初始值
		while(low <= high)
		{
				mid = (low + high) / 2;
				if(ST.R[mid].key == key)
				{
						return mid;//找到待查找元素
				}
				else if(key < St.R[mid].key)
				{
						high = mid -1;//将查找区间缩小到 mid 左边
				}
		
				else
				{
						low = mid + 1;//将查找区间缩到 mid 右边
				}
		}
		return 0;
}

折半查找性能分析 - 判定树

折半查找过程可以用二叉树来描述

  • 树中每一个结点对应表中一个记录,但结点值不是记录的关键字,而是记录在表中的位置序号。
  • 把当前查找区间的中间位置作为根,左子表和右子表分别作为根的左子树和右子树,由此得到的二叉树称为折半查找的判定树
  • 结点所在层数表示该位置的元素需要比较多少次。

在这里插入图片描述

查找成功

  • 比较次数 = 路径上的结点数
  • 比较次数 = 结点所在的层数

在这里插入图片描述
在这里插入图片描述

查找不成功

  • 比较次数 = 路径上的内部结点数
  • 比较次数 <= log₂n + 1。

在这里插入图片描述

  • 假设每个元素的查找概率相等,求查找成功时的平均查找长度。
    • 所有元素的比较次数相加然后除与结点数。

在这里插入图片描述

平均查找长度 ASL(成功时)

  • 设表长 n = 2h -1,则 h = log₂(n+1)(此时,判定树为深度 = h 的满二叉树),且表中每个记录的查找概率相等:Pi = 1/n

在这里插入图片描述

折半查找特点

  • 缺点:效率比顺序查找搞。
  • 缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)。

7.2.3 分块查找

分块查找:既能使查找效率比较高,又能方便的进行插入和删除。

分快查找算法

  • 一般的字典(图1)俺们是用二分查找的方式来找的,随便翻开一页看到当前单词页的首字母,就知道是该往前还是往后翻了。
  • 而不一般的字典(图2),将所有的单词按照首字母顺序划分成若干块,将这本书分成 26 块区域。
    • 假设要找下面这个单词,直接翻开首字母为 m 的那一块区域,然后在这块区域进行 顺序查找 或者 二分查找。
  • 这种查找方式就称作分块查找,也称索引顺序查找

在这里插入图片描述

分块查找条件

  1. 将表所有元素分成若干块,每一块的内容可以是有序的,也可以是无序的,如果是无序则称作分块有序
    • 分块有序块间有序,块内无序
      • 块之间是有序的,单词是按 A ~ Z这样一个区域块排的,块内可以是无序的。都是字母 m 开头的单词可以随便放(当然字典不能真的随便放)。
    • 定义:若第 i 块在第 j 块之前(i < j),则第 j 块中所有记录的关键字均大于第 i 块中的最大关键字。
      • 如:假设现有一个被分成 3 块的数据表,第一块中的最大值 22 肯定小于第 2、3 块中所有的值。

在这里插入图片描述

  1. 建立索引表(每个结点含有最大关键字域或指向本块第一个结点的指针,且按关键字有序)。
    • 人话:记录每一块区域的最大值,以及每一块是从哪里开始的。

在这里插入图片描述

分快查找过程

  1. 先确定待查找记录(值)在哪块区域(用顺序或折半查找)。
  2. 再在块内查找(用顺序查找)。

举个例子

在这里插入图片描述

  1. 先在索引表中找,第一块区域最大值是 22,那肯定不在第一块,38 < 48,所以在第二块区域找。
  2. 块内元素是无序的,所以就在第二块中进行顺序查找。

分块查找算法分析及比较

分块查找的平均查找次数为:在块之间比较的次数 + 块内查找的次数。

查找效率

在这里插入图片描述

  • 其中:Lb 为查找索引表确定所在块的平均查找长度,Lw 为在块中查找元素的平均查找长度。

在这里插入图片描述

  • 假设总共有 n 个元素,再假设每一块中有 s 个元素,所以索引表就可以分成 n / s 块。
    • 在索引表中的平均查找长度就为:log₂(n / s +1)
    • 在块内进行查找:因为块内是无序的,无序就用顺序查找法,顺序查找的凭据查找长度就是 s / 2

例如:

当 n = 9,s = 3 时

  • 分块法的 ASLbs = 3.5。
  • 折半法的 ASL ≈ log₂n = 3.1。但是折半法需要预先排序,所以任然需要时间。
  • 顺序法的 ASL = (1+n)/2 = 5。

分块查找特点

  • 优点:插入和删除比较容易,无序进行大量移动。
  • 缺点:要增加一个索引表的存储空间并对初始索引表进行排序运算。
  • 适用情况:如果线性表既要快速查找又经常动态变化,则可以采用分块查找。

查找方法比较

在这里插入图片描述

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

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

相关文章

背景颜色和背景图片

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <!--这行代码是告诉浏览器需要使用"utf-8"字符集打开 因为HBuilder工具是采用utf-8编码的 注意&#xff1a;并不是设置当前页面的字符集编码方式--> …

SpringMVC(十二):SpringMVC文件下载

文章目录 SpringMVC文件下载 一、下载之前的准备 二、下载的基本流程 三、下载的请求数据 1、下载的后台实现 2、下载的示例代码 SpringMVC文件下载 一、下载之前的准备 展示所有玩家信息&#xff0c;包括图片展示。 <% page contentType"text/html;charset…

Linux_常见命令

1.ls ls -l 列出隐藏文件&#xff0c;并显示10项权限,类似如同下图 在部分发行版本的linux下&#xff0c;ll等同于ls -l 首先&#xff0c;第一列为-则代表着这一列是文件&#xff0c; 第一列为d则代表这一列为目录 除了第一位&#xff0c;那么其他还有9位&#xff0c;分为3组…

学习shell与shell script 02_vim 的保存恢复与打开时的警告信息

[1] Stopped vim test.txt $kill -9 %1[1] Stopped vim test.txt $jobs [1] Killed vim test.txt编辑一个文件后&#xff0c;使用Ctrl z 挂起。然后被不正常中断&#xff0c;导致暂存盘无法通过正常的流程来结束。所以暂…

AHB协议(2/2)

Charpter 4 Bus Interconnection 4.1 互联结构 互联结构在系统中提供了M端和S端的连接。单一的M端只需要使用一个解码器和多路选择器。 一个多M端的系统中需要使用提供仲裁和将信号从不同的M端分发到对应的S端的互联结构。分发结构需要地址&#xff0c;控制信号和写数据。 4…

ARM uboot的常用命令

一、uboot 的常用命令1 1、类似 linux 终端的行缓冲命令行 (1) 行缓冲的意思就是&#xff1a;当我们向终端命令行输入命令的时候&#xff0c;这些命令没有立即被系统识别&#xff0c;而是被缓冲到一个缓存区&#xff08;也就是系统认为我们还没有输入完&#xff09;&#xff…

2.5 变量与常量

文章目录1.变量1.1 变量的声明1.2 变量的命名1.3 变量的初始化1.4 变量的使用2 常量1.变量 和其他的编程语言一样&#xff0c;JAVA也是用变量来存储值的&#xff0c;常量可以理解为一种特殊的变量&#xff0c;其特殊在它的值是不变的。 1.1 变量的声明 声明变量本质就是创造…

自动驾驶感知——环境感知的基本概念

文章目录1. 智能汽车概述1.1 汽车新四化1.2 智能网联汽车1.3 SAE J3016自动驾驶分级标准2. 环境感知定义2.1 智能网联汽车系统架构2.2 环境感知定义及对象3. 各类传感器的介绍4. 环境感知经典算法概述5. 自动驾驶仿真软件的功能5.1 背景介绍5.2 自动驾驶仿真软件平台背后的科学…

(二十六)Set系列集合

简介: Set集合&#xff0c;基础自Collection。特征是插入无序&#xff0c;不可指定位置访问。Set集合的实现类可说是基于Map集合去写的。通过内部封装Map集合来实现的比如HashSet内部封装了HashMap。Set集合的数据库不能重复&#xff08; 或 eqauls&#xff09;的元素Set集合的…

AxMath使用教程(持续更新中)

前言 这两天学了学Latex&#xff0c;主要是为了以后写毕业论文做铺垫&#xff0c;而且Latex在数学公式这一方面&#xff0c;要比Word方便许多&#xff0c;于是我就下载了一款国产的公式编辑器——AxMath。永久会员不贵&#xff0c;只要36元&#xff0c;而且软件很好用&#xf…

【自然语言处理】情感分析(一):基于 NLTK 的 Naive Bayes 实现

情感分析&#xff08;一&#xff09;&#xff1a;基于 NLTK 的 Naive Bayes 实现朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类器可以用来确定输入文本属于某一组类别的概率。例如&#xff0c;预测评论是正面的还是负面的。 它是 “朴素的”&#xff0c;它假设文本中的单…

机器学习: Label vs. One Hot Encoder

如果您是机器学习的新手&#xff0c;您可能会对这两者感到困惑——Label 编码器和 One-Hot 编码器。这两个编码器是 Python 中 SciKit Learn 库的一部分&#xff0c;它们用于将分类数据或文本数据转换为数字&#xff0c;我们的预测模型可以更好地理解这些数字。今天&#xff0c…

图机器学习-节点嵌入(Node Embedding)

图机器学习-节点嵌入(Node Embedding) Node Embedding简单点来说就是将一个node表示为一个RdR^dRd的向量。 EncoderDecoder Framework 我们首先需要设计一个encoder对节点进行编码。既然要比较相似度那么我就需要定义节点的相似度。同时我们还需要定义一个decoder&#xff0…

Java线程的生命周期的五种状态

在java中&#xff0c;任何对象都要有生命周期&#xff0c;线程也不例外&#xff0c;它也有自己的生命周期。当Thread对象创建完成时&#xff0c;线程的生命周期便开始了&#xff0c;当run()方法中代码正常执行完毕或者线程抛出一个未捕获的异常(Exception)或者错误(Error)时&am…

通信原理简明教程 | 数字基带传输

文章目录1数字基带传输系统的基本组成2 数字基带信号及其频域特性2.1 基本码型2.2 常用码型2.3 数字基带信号的功率谱3 码间干扰3.1 码间干扰的概念&#xff08;ISI&#xff09;3.2 无码间干扰传输的条件3.3 无码间干扰的典型传输波形4 部分响应和均衡技术&#xff08;*&#x…

java+ssm网上书店图书销售评价系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 2 第3章 系统分析 4 3.1 需求分析 4 3.2 系统可行性分析 4 3.2.1技术可行性&#xff1a;技术背景 4 3.2.2经…

【蓝桥云课】位运算

一、原码、反码、补码 原码&#xff1a;符号位&#xff08;正数为0、负数为1&#xff09;二进制数 反码&#xff1a;正数的反码正数的原码&#xff1b;负数的反码负数的原码除符号位外按位求反 补码&#xff1a;正数的补码正数的反码&#xff1b;负数的补码负数的反码1 整数原…

基于SPN实现的密码学课程设计(附完整代码)

就是如图所示的一个过程! 1.1 初次写SPN 初代SPN 为了方便的使用S盒P盒的那些运算(直接使用数组, 而不使用位运算),所以想起了C语言课上学的

HTML基本常用标签

<!doctype html> <html> <head> <title>HTML的常用标签</title> <meta charset"UTF-8"> <!-- 这行代码是告诉浏览器使用UTF-8字符集打开; 而不是设置当前页面的编码方式 --> </head> <bo…

SSH命令

概念 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中建立安全隧道&#xff08;secure channel&#xff09;来实现SSH客户端与服务器之间…