22.查找,线性表的查找

news2024/11/17 14:41:05

目录

一. 查找的基本概念

二. 线性表的查找

(1)顺序查找(线性查找)

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

(3)分块查找


一. 查找的基本概念

查找表是由同一类型的数据元素(或记录)构成的集合。由于“集合”中的数据元素之间存在着松散的关系,因此查找表是一种应用灵便的结构。例如:每个同学的考号和成绩。

查找——根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素或(记录)。

关键字用来标识一个数据元素(或记录)的某个数据项的值。

  • 主关键字:可唯一地标识一个记录的关键字是主关键字;(如:准考证号,每个准考证号唯一确定一名考生)
  • 次关键字:反之,用以识别若干记录的关键字是次关键字。(如:物理成绩,可能物理同一分数有很多人)

若查找表中存在这样一个记录,则称“查找成功”。查找结果给出整个记录的信息,或指示该记录在查找表中的位置;否则称“查找不成功”。查找结果给出“空记录”或“空指针”。

对查找表经常进行的操作:

  • 查询某个“特定的”数据元素是否在查找表中;
  • 检索某个“特定的”数据元素的各种属性;
  • 在查找表中插入一个数据元素;
  • 删除查找表中的某个数据元素。

查找表可以分为两类。静态查找表是仅作查询”(检索)操作的查找表。动态查找表是作"插入”和“删除”操作的查找表。有时在查询之后,还需要将查询结果为“不在查找表中”的数据元素插入到查找表中;或者,从查找表中删除其“查询”结果为“在查找表中”的数据元素,此类表为动态查找表。

查找算法的评价指标:关键字的平均比较次数,也称平均查找长度ASL(Average Search Length)ASL=\sum_{i=1}^{n}p_ic_i;其中:n:记录的个数;pi:查找第i个记录的概率(通常认为pi =1/n);ci:找到第i个记录所需的比较次数;

查找的方法取决于查找表的结构,即表中数据元素是依何种关系组织在一起的。由于对查找表来说,在集合中查询或检索一个“特定的”数据元素时,若无规律可循,只能对集合中的元素一一加以辨认直至找到为止。而这样的“查询”或“检索”是任何计算机应用系统中使用频度都很高的操作,因此设法提高查找表的查找效率,是本节讨论问题的出发点。为提高查找效率,一个办法就是在构造查找表时,在集合中的数据元素之间人为地加上某种确定的约束关系。

二. 线性表的查找

(1)顺序查找(线性查找)

应用场景:顺序表或线性链表表示的静态查找表,表内元素之间无序。

数据元素类型定义如下:

typedef struct{
    KeyType key;  //关键字域
    int math;  //其他域
}ElemType;

typedef struct {  //顺序表结构类型定义
    ElemType *R;  //表基址
    int length;  //表长
}SSTable;  //Sequential Search Table

SSTable ST;  //定义顺序表ST

我们从后往前比较,不难写出顺序查找的算法:

int Search_Seq(SSTable ST, KeyType key){  //Keytype根据问题需要自己设置
    //若成功返回其位置信息,否则返回0
    for(i=ST.length; i>=1; --i)
        if (ST.R[i].key==key) return i;  //ST.R[i].key就是i元素的Key值
    return 0;
}

当然这个算法有很多其他形式,这里给出一种:

int Search_Seq(SSTable ST,KeyType key){
    for (i = ST.length; ST.R[i].key != key; --i);  //注意后面有分号
        if (i <= 0) break;
    if (i > 0) return i;
    else return 0;
}

上述算法的每一个元素都要判断两次:一是i是否大于1,二是元素是否相等。我们可否简化一下比较步骤?我们把待查关键字key存入表头(“哨兵”、”监视哨”),从后往前逐个比较,可免去查找过程中每一步都要检测是否查找完毕,加快速度。这样,若表中不存在,则返回结果自然是0,就取消了检查越界的操作。

int Search_Seq(SSTable ST,KeyType key){
    ST.R[0].key = key;
    for (i = ST.length; ST.R[i].key != key; --i);  //注意后面有分号
    return i;
}

下面分析顺序查找法的时间效率。比较次数与key位置有关:查找第i个元素,需要比较n-i+1次;查找失败,需比较n+1次。所以,算法的时间复杂度是O(n),查找成功时的平均查找长度是:

ASL=\sum_{i=1}^{n}p_ic_i=\frac{1}{n}\sum_{i=1}^{n}(n-i+1)=\frac{n+1}{2}

空间复杂度:一个辅助空间O(1);

讨论:(1)记录的查找概率不相等时如何提高查找效率?
查找表存储记录原则——按查找概率高低存储:查找概率越高,比较次数越少;查找概率越低,比较次数较多。
(2)记录的查找概率无法测定时如何提高查找效率?
方法——按查找概率动态调整记录顺序:

  • 在每个记录中设一个访问频度域;
  • 始终保持记录按非递增有序的次序排列;
  • 每次查找后均将刚查到的记录直接移至表头。

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

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

特点:针对有序序列,每次将待查区间的长度缩小一半。

设表长为n,low、high和mid分别指向待查元素所在区间的上界、下界和中点,key为给定的要查找的值:

  • 初始时,令low=1,high=n,mid=L(low+high)/2];
  • 让k与mid指向的记录比较若key==R[mid].key,查找成功;若key<R[mid].key,则high=mid-1;若key>R[mid].key,则 low=mid+1;
  • 重复上述操作,直至low>high时,查找失败;
int Search_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;  //继续在前半区间进行查找
        else 
            low = mid + 1;  //继续在后半区间进行查找
    }
    return 0;  //顺序表中不存在待查元素
}  //Search_Bin

我们也可以用递归方法书写:

int Search_Bin(SSTable ST, keyType key, int low, int high){
    if(low > high) return 0;  //查找不到时返回0
    mid = (low+high)/2;
    if(key == ST.elem[mid].key) 
        return mid;
    else if(key<ST.elem[mid].key)
        Search_Bin(ST, key, low, mid-1);  //递归,在前半区间进行查找
    else
        Search_Bin(ST, key, mid+1, high);  //递归,在后半区间进行查找
}

下面分析折半查找法的性能。分析每个位置需要查找几次,我们可以画出判定树:

假设表长n=2^h-1,则有h=log_2(n+1),此时判定树是高度为h的满二叉树。且假设表中每个元素查找的概率相等,p=\frac{1}{n}。不难得到:

ASL_{bs}=\frac{1}{n}\sum_{j=1}^{h}j\cdot 2^{j-1}=\frac{(h-1)2^h+1}{n}=\frac{n+1}{n}log_2(n+1)-1\approx log_2(n+1)-1(n>50)

折半查找优点:效率比顺序查找高。时间复杂度是O(lg n);
折半查找缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)。

(3)分块查找

举例:查字典,字典的编写把A-Z分成26块。分块查找的实质是索引顺序表上的查找。

方法:(1)将表分成几块,且分块有序(若i<j,则第j块中所有记录的关键字均大于第i块中的最大关键字),每块内的元素可以有序或无序;
(2)建立“索引表”(每个结点含有最大关键字域和指向本块第一个结点的指针,且按关键字有序)。

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

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

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

相关文章

深度学习11:Transformer

目录 什么是 Transformer&#xff1f; Encoder Decoder Attention Self-Attention Context-Attention 什么是 Transformer&#xff08;微软研究院笨笨&#xff09; RNN和Transformer区别 Universal Transformer和Transformer 区别 什么是 Transformer&#xff1f; ​ …

python下timer定时器常用的两种实现方法

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 话不多说&#xff0c;直接开搞&#xff0c;如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 方法一&#xff0c;使用线程中现成的&#xff1a; 这种一般比较常用&#xff0c;特别是在线程中的使用方法&#xff0c;下…

python3GUI--PyQt5打包心得(详细图文演示)

文章目录 一&#xff0e;前言二&#xff0e;准备工作&介绍1.准备2.介绍1.pyinstaller2.pipenv 三&#xff0e;项目打包1.准备2.打包1.打包参数2.虚拟环境 三&#xff0e;总结 一&#xff0e;前言 有朋友私信问我&#xff0c;如何把项目打包和如何减小打包后的文件体积。笔…

HarmonyOS应用开发者高级认证练习题

系列文章目录 HarmonyOS应用开发者基础认证练习题 HarmonyOS应用开发者高级认证练习题 文章目录 系列文章目录前言一、判断二、单选三、多选 前言 本文所有内容来源于个人进行HarmonyOS应用开发者系列认证的学习过程中所做过的练习题&#xff0c;所有答案均是个人作答&#x…

深度学习4. 循环神经网络 – Recurrent Neural Network | RNN

目录 循环神经网络 – Recurrent Neural Network | RNN 为什么需要 RNN &#xff1f;独特价值是什么&#xff1f; RNN 的基本原理 RNN 的优化算法 RNN 到 LSTM – 长短期记忆网络 从 LSTM 到 GRU RNN 的应用和使用场景 总结 百度百科维基百科 循环神经网络 – Recurre…

css滚动条样式这样修改下很漂亮

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>滚动条样式修改下很漂亮(不支持IE)</title> <style type"text/css"> * { margin: 0; padding: 0; } .box { width: 300px; height: 100px; margin…

Linux系统编程:线程控制

目录 一. 线程的创建 1.1 pthread_create函数 1.2 线程id的本质 二. 多线程中的异常和程序替换 2.1 多线程程序异常 2.2 多线程中的程序替换 三. 线程等待 四. 线程的终止和分离 4.1 线程函数return 4.2 线程取消 pthread_cancel 4.3 线程退出 pthread_exit 4.4 线程…

在编辑器中使用正则

正则是一种文本处理工具&#xff0c;常见的功能有文本验证、文本提取、文本替换、文本切割等。有一些地方说的正则匹配&#xff0c;其实是包括了校验和提取两个功能。 校验常用于验证整个文本的组成是不是符合规则&#xff0c;比如密码规则校验。提取则是从大段的文本中抽取出…

探索AIGC人工智能(Midjourney篇)(二)

文章目录 利用Midjourney进行LOGO设计 用ChatGPT和Midjourney的AI绘画&#xff0c;制作儿童绘本故事 探索Midjourney换脸艺术 添加InsightFaceSwap机器人 Midjourney打造专属动漫头像 ChatGPT Midjourney画一幅水墨画 Midjourney包装设计之美 Midjourney24节气海报插画…

【车载开发系列】常用开发工具一览

【车载开发系列】常用开发工具一览 常用开发工具一览 【车载开发系列】常用开发工具一览一. HexView(十六进制查看编辑器)二. VSB Vehicle Systems Builder三. MULTI IDE四. CANoe五. CANalyzer网络分析测试工具六. CasePlayer2七. Renesas Flash Programmer八. Ecu Spectrum九…

红黑树基础理解

一、数据结构 1.数组 a.内存地址连续&#xff0c;使用之前必须要指定数组长度 b.可以通过下标访问的方式访问成员&#xff0c;查询效率高 c.增删操作会带来性能消耗效率相对差点(要防止数据下标越界的问题&#xff0c;需要动态扩容&#xff09; 2.链表 &#xff1a;单向链表…

ICP算法

一、ICP 迭代最接近点&#xff08;ICP&#xff09;&#xff1a;给定两个点集。估计R&#xff0c;t以对齐两个点。 找到点的对应关系估算R&#xff0c;t基于R&#xff0c;t&#xff0c;计算误差和分数重复执行上述步骤直到收敛 传统ICP&#xff1a;根据距离进行计算&#xff0c…

使用Python统计小说语言描写的字数

说明&#xff1a;最早出现这个需求&#xff0c;来自博主阅读《罪与罚》&#xff0c;书中陀思妥耶夫斯基有太多的语言描述&#xff0c;以至于我想知道这本书中到底出现了多少对白。文本介绍如果使用python程序统计一本书中的对话&#xff0c;角色名称&#xff0c;标点符号。 找…

深度学习模型数值稳定性——梯度衰减和梯度爆炸的说明

文章目录 0. 前言1. 为什么会出现梯度衰减和梯度爆炸&#xff1f;2. 如何提高数值稳定性&#xff1f;2.1 随机初始化模型参数2.2 梯度裁剪&#xff08;Gradient Clipping&#xff09;2.3 正则化2.4 Batch Normalization2.5 LSTM&#xff1f;Short Cut&#xff01; 0. 前言 按照…

读取SD卡图片bin文件显示LCD上

读取SD卡bin文件显示图片 Coding 环境搭建&#xff1a; 硬件平台&#xff1a;STM32H750XBH6开发环境&#xff1a;STM32CubeMX V6.8.1KEIL V5.28.0.0STM32H750固件版本&#xff1a;package V1.11.0仿真下载驱动&#xff1a;ST-Link 前言&#xff1a;STM32H750XBH6 的flash只…

零基础学习正演的数值模拟(含代码)

摘要: 本贴从零开始学习正演的数值模拟方法. 包括相应的偏微分基础、声波方程、雷克子波、均匀速度场的模拟、一般速度场的模拟. 1. 偏微分基础 本小节仅涉及高等数学相关知识, 与领域无关. 1.1 导数 引例: 物体从一维坐标的原点开始移动, 在 t t t 时刻, 它在坐标轴的位置…

汤普森采样(Thompson sampling): 理论支持

目录 一、UCB与TS算法数学原理1、Upper Confidence Bounds 数学原理2、Thompson sampling 数学原理a、TS 基本数据原理1. beta 分布2. 共轭分布与共轭先验3. 采样的编程实现 b、TS 算法流程1. TS算法基础版本2. Batched Thompson Sampling 二、UCB与TS算法的优缺点1、TS算法的优…

Ubuntu释放VMware虚拟磁盘未使用空间

By: Ailson Jack Date: 2023.08.26 个人博客&#xff1a;http://www.only2fire.com/ 本文在我博客的地址是&#xff1a;http://www.only2fire.com/archives/152.html&#xff0c;排版更好&#xff0c;便于学习&#xff0c;也可以去我博客逛逛&#xff0c;兴许有你想要的内容呢。…

基于Java+SpringBoot+Vue前后端分离医院后台管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Spring为什么要专门定义BeanDefinition ,有Class不行吗?

前言 创建一个Java Bean&#xff0c;大概是下面这个流程&#xff1a; 我们写的Java文件&#xff0c;会编译为Class文件&#xff0c;运行程序&#xff0c;类加载器会加载Class文件&#xff0c;放入JVM的方法区&#xff0c;我们就可以愉快的new对象了。 创建一个Spring Bean&am…