查找表算法

article/2025/9/16 23:24:26

查找表是由同一类型的数据元素构成的集合。
一般对于查找表有一下几种操作:
1、在查找表中查找某个具体的数据元素;
2、在查找表中插入数据元素;
3、从查找表中删除数据元素。
静态查找表和动态查找表
在查找表中只做查找操作,不带动表中数据元素,称此类查找表为静态查找表;反之,在查找表中查找操作的同时进行插入数据或者删除数据的操作,称此类表为动态查找表。

静态查找表既可以使用顺序表表示,也可以使用链表结构表示。虽然一个是数组、一个链表,但两者在做查找操作时,基本上大同小异。

顺序查找的实现

静态查找表用顺序存储结构表示时,顺序查找的查找过程为:从表中的最后一个数据元素开始,逐个同记录的关键字做比较,如果匹配成功,则查找成功;反之,如果直到表中第一个关键字查找完也没有成功匹配,则查找失败。

#include <stdio.h>
#include <stdlib.h>
#define keyType int
typedef struct {keyType key;//查找表中每个数据元素的值//如果需要,还可以添加其他属性
}ElemType;
typedef struct{ElemType *elem;//存放查找表中数据元素的数组int length;//记录查找表中数据的总数量
}SSTable;
//创建查找表
void Create(SSTable **st,int length){(*st)=(SSTable*)malloc(sizeof(SSTable));(*st)->length=length;(*st)->elem =(ElemType*)malloc((length+1)*sizeof(ElemType));printf("输入表中的数据元素:\n");//根据查找表中数据元素的总长度,在存储时,从数组下标为 1 的空间开始存储数据for (int i=1; i<=length; i++) {scanf("%d",&((*st)->elem[i].key));}
}
//查找表查找的功能函数,其中key为关键字
int Search_seq(SSTable *st,keyType key){st->elem[0].key=key;//将关键字作为一个数据元素存放到查找表的第一个位置,起监视哨的作用int i=st->length;//从查找表的最后一个数据元素依次遍历,一直遍历到数组下标为0while (st->elem[i].key!=key) {i--;}//如果 i=0,说明查找失败;反之,返回的是含有关键字key的数据元素在查找表中的位置return i;
}
int main() {SSTable *st;Create(&st, 6);getchar();printf("请输入查找数据的关键字:\n");int key;scanf("%d",&key);int location=Search_seq(st, key);if (location==0) {printf("查找失败");}else{printf("数据在查找表中的位置为:%d",location);}return 0;
}

输入表中的数据元素:
1 2 3 4 5 6
请输入查找数据的关键字:
2
数据在查找表中的位置为:2

同时,在程序中初始化创建查找表时,由于是顺序存储,所以将所有的数据元素存储在数组中,但是把第一个位置留给了用户用于查找的关键字。例如,在顺序表{1,2,3,4,5,6}中查找数据元素值为 7 的元素,则添加后的顺序表为:


顺序表中的监视哨
图 1 顺序表中的监视哨


顺序表的一端添加用户用于搜索的关键字,称作“监视哨”。

放置好监视哨之后,顺序表遍历从没有监视哨的一端依次进行,如果查找表中有用户需要的数据,则程序输出该位置;反之,程序会运行至监视哨,此时匹配成功,程序停止运行,但是结果是查找失败。

折半查找算法

折半查找,也称二分查找,在某些情况下相比于顺序查找,使用折半查找算法的效率更高。但是该算法的使用的前提是静态查找表中的数据必须是有序的

例如,在{5,21,13,19,37,75,56,64,88 ,80,92}这个查找表使用折半查找算法查找数据之前,需要首先对该表中的数据按照所查的关键字进行排序:{5,13,19,21,37,56,64,75,80,88,92}

在折半查找之前对查找表按照所查的关键字进行排序的意思是:若查找表中存储的数据元素含有多个关键字时,使用哪种关键字做折半查找,就需要提前以该关键字对所有数据进行排序。

对静态查找表{5,13,19,21,37,56,64,75,80,88,92}采用折半查找算法查找关键字为 21 的过程为:
 


图 1 折半查找的过程(a)


如上图 1 所示,指针 low 和 high 分别指向查找表的第一个关键字和最后一个关键字,指针 mid 指向处于 low 和 high 指针中间位置的关键字。在查找的过程中每次都同 mid 指向的关键字进行比较,由于整个表中的数据是有序的,因此在比较之后就可以知道要查找的关键字的大致位置。

例如在查找关键字 21 时,首先同 56 作比较,由于21 < 56,而且这个查找表是按照升序进行排序的,所以可以判定如果静态查找表中有 21 这个关键字,就一定存在于 low 和 mid 指向的区域中间。

因此,再次遍历时需要更新 high 指针和 mid 指针的位置,令 high 指针移动到 mid 指针的左侧一个位置上,同时令 mid 重新指向 low 指针和 high 指针的中间位置。如图 2 所示:
 


图 2 折半查找的过程(b)
 

同样,用 21 同 mid 指针指向的 19 作比较,19 < 21,所以可以判定 21 如果存在,肯定处于 mid 和 high 指向的区域中。所以令 low 指向 mid 右侧一个位置上,同时更新 mid 的位置。
 


图 3 折半查找的过程(3)

当第三次做判断时,发现 mid 就是关键字 21 ,查找结束。

注意:在做查找的过程中,如果 low 指针和 high 指针的中间位置在计算时位于两个关键字中间,即求得 mid 的位置不是整数,需要统一做取整操作。

#include <stdio.h>
#include <stdlib.h>
#define keyType int
typedef struct {keyType key;//查找表中每个数据元素的值//如果需要,还可以添加其他属性
}ElemType;
typedef struct{ElemType *elem;//存放查找表中数据元素的数组int length;//记录查找表中数据的总数量
}SSTable;
//创建查找表
void Create(SSTable **st,int length){(*st)=(SSTable*)malloc(sizeof(SSTable));(*st)->length=length;(*st)->elem = (ElemType*)malloc((length+1)*sizeof(ElemType));printf("输入表中的数据元素:\n");//根据查找表中数据元素的总长度,在存储时,从数组下标为 1 的空间开始存储数据for (int i=1; i<=length; i++) {scanf("%d",&((*st)->elem[i].key));}
}
//折半查找算法
int Search_Bin(SSTable *ST,keyType key){int low=1;//初始状态 low 指针指向第一个关键字int high=ST->length;//high 指向最后一个关键字int mid;while (low<=high) {mid=(low+high)/2;//int 本身为整形,所以,mid 每次为取整的整数if (ST->elem[mid].key==key)//如果 mid 指向的同要查找的相等,返回 mid 所指向的位置{return mid;}else if(ST->elem[mid].key>key)//如果mid指向的关键字较大,则更新 high 指针的位置{high=mid-1;}//反之,则更新 low 指针的位置else{low=mid+1;}}return 0;
}
int main(int argc, const char * argv[]) {SSTable *st;Create(&st, 11);getchar();printf("请输入查找数据的关键字:\n");int key;scanf("%d",&key);int location=Search_Bin(st, key);//如果返回值为 0,则证明查找表中未查到 key 值,if (location==0) {printf("查找表中无该元素");}else{printf("数据在查找表中的位置为:%d",location);}return 0;
}

以图 1 的查找表为例,运行结果为:

输入表中的数据元素:
5 13 19 21 37 56 64 75 80 88 92
请输入查找数据的关键字:
21
数据在查找表中的位置为:4

总结

通过比较折半查找的平均查找长度,同前面介绍的顺序查找相对比,明显折半查找的效率要高。但是折半查找算法只适用于有序表,同时仅限于查找表用顺序存储结构表示。

当查找表使用链式存储结构表示时,折半查找算法无法有效地进行比较操作(排序和查找操作的实现都异常繁琐)。

 

分块查找算法,索引顺序查找算法

如,采用分块查找法在有序表 11、12、18、28、39、56、69、89、96、122、135、146、156、256、298 中查找关键字为 96 的元素。

査找特定关键字元素个数为 15,要求用户输入有序表各元素,程序输出査找成功与否,若成功,还显示元素在有序表中的位罝。

实现过程:

(1)定义结构体 index,用于存储块的结构,并定义该结构体数组 index_table。

(2)自定义函数 block_search(),实现分块查找。

(3) main() 函数作为程序的入口函数。程序代码如下:

#include <stdio.h>
struct index    //定义块的结构
{int key;    //块的关键字int start;    //块的起始值int end;    //块的结束值
}index_table[4];    //定义结构体数组
int block_search(int key,int a[])    //自定义实现分块查找
{int i,j;i=1;while(i<=3&&key>index_table[i].key)    //确定在哪个块中i++;if(i>3)    //大于分得的块数,则返回0return 0;j=index_table[i].start;    //j等于块范围的起始值while(j<=index_table[i].end&&a[j]!=key)    //在确定的块内进行顺序查找j++;if(j>index_table[i].end)    //如果大于块范围的结束值,则说明没有要査找的数,j置0j = 0;return j;
}
int main()
{int i,j=0,k,key,a[16];printf("请输入15个数:\n");for(i=1;i<16;i++)scanf("%d",&a[i]);    //输入由小到大的15个数for(i=1;i<=3;i++){index_table[i].start=j+1;    //确定每个块范围的起始值j=j+1;index_table[i].end=j+4;    //确定每个块范围的结束值j=j + 4;index_table[i].key=a[j];    //确定每个块范围中元素的最大值}printf("请输入你想査找的元素:\n");scanf("%d",&key);    //输入要查询的数值k=block_search(key,a);    //调用函数进行杳找if(k!=0)printf("查找成功,其位置是:%d\n",k);    //如果找到该数,则输出其位置elseprintf("查找失败!");    //若未找到,则输出提示信息return 0;
}
运行结果:
请输入15个数:
11 12 18 28 39 56 69 89 96 122 135 146 156 256 298
请输入你想査找的元素:
96
查找成功,其位置是:9

技术要点:

分块査找也称为索引顺序査找,要求将待查的元素均匀地分成块,块间按大小排序,块内不排序,所以要建立一个块的最大(或最小)关键字表,称为索引表。

本实例中将给出的 15 个数按关键字大小分成了 3 块,这 15 个数的排列是一个有序序列,也可以给出无序序列,但必须满足分在第一块中的任意数都小于第二块中的所有数,第二块中的所有数都小于第三块中的所有数。当要査找关键字为 key 的元素时,先用顺序杳找在已建好的索引表中查出 key 所在的块中,再在对应的块中顺序查找 key,若 key 存在,则输出其相应位置,否则输出提示信息。

 

总结:二分查找和分块超查找要基于数据是有序的,才可以实现。所在在查找之前要进行数据的排序。

二叉排序树(二叉查找树)及C语言实现

http://c.biancheng.net/view/3431.html

 

 


http://chatgpt.dhexx.cn/article/IV73njOp.shtml

相关文章

数据结构之查找表

前言 今天学习数据结构看到了一个词-静态查找表&#xff0c;还有与之对应的动态查找表&#xff0c;然后我发现。 啊&#xff0c;这是个啥&#xff0c;好像知道又好像不知道&#xff0c;不就是查找吗&#xff0c;干嘛弄这些专业的说法&#xff0c;回头翻了一下数据结构的书&am…

数据结构查找表详解(包含常用查找算法)

** 1. 什么是查找表 ** 在日常生活中&#xff0c;几乎每天都要进行一些查找的工作&#xff0c;在电话簿中查阅某个人的电话号码&#xff1b;在电脑的文件夹中查找某个具体的文件等等。本节主要介绍用于查找操作的数据结构——查找表。 查找表是由同一类型的数据元素构成的集…

FPGA工作原理

一.查找表&#xff08;Look-Up-Table)的原理与结构 采用这种结构的PLD芯片我们也可以称之为FPGA&#xff1a;如altera的ACEX,APEX系列,xilinx的Spartan,Virtex系列等。 查找表&#xff08;Look-Up-Table)简称为LUT&#xff0c;LUT本质上就是一个RAM。 目前FPGA中多使用4输入的…

FPGA知识积累【3】

目录 1.查找表&#xff08;LUT&#xff09;原理与结构2.FPGA基本结构3.FPGA的RAM、ROM、CAM4.硬件语言的层次5.寄生效应6.线与逻辑7.竞争冒险8.消除竞争冒险的方法 1.查找表&#xff08;LUT&#xff09;原理与结构 ①查找表简称LUT&#xff0c;本质上就是一个RAM。目前FPGA中多…

数据结构导论【六】之 查找表

感谢内容提供者&#xff1a;金牛区吴迪软件开发工作室 接上一篇&#xff1a;数据结构导论【五】之 图 文章目录 一、基本概念二、静态查找表的实现1.顺序表上的查找 -- 顺序查找a.过程b.算法c.算法分析 2.有序表上的查找 -- 二分查找a.二分查找思想b.二分查找过程c.二分查找算法…

查找表(Lookup table)

查找表&#xff08;look-up-table&#xff09;这个名字很好听&#xff0c;缩写 LUT&#xff0c;听起来很高端&#xff0c;其实是一种很简单高效的索引操作&#xff0c;今天简单介绍一下。 是啥 wiki定义&#xff1a; a lookup table is an array that replaces runtime computa…

从底层结构开始学习FPGA(2)----LUT查找表

文章目录 系列目录与传送门 一、概述 二、实现原理 系列目录与传送门 《从底层结构开始学习FPGA》目录与传送门 一、概述 记得刚接触FPGA的时候&#xff0c;总能看见类似这样的一句话----FPGA是基于查找表LUT的可编程逻辑器件。FPGA常常被人比作“数字积木”&#xff0c;就是因…

码,主码,主属性,非主属性,平凡函数依赖,完全依赖等词解释

码&#xff1a;代表数目的符号 主码 我们在建立数据库的时候&#xff0c;需要为每张表指定一个主码&#xff0c;主码也叫主键。 所谓主码就是在实体集中区分不同实体的候选码。 一个实体集中只能有一个主码&#xff0c;但可以有多个候选码。 必须注意两点&#xff1a; 1.主…

SpringBoot项目打jar后执行jar包提示:xx没有主属性清单 解决

SpringBoot项目打jar包后执行jar包提示&#xff1a;xx没有主属性清单 解决 今天在练习SpringBoot项目打jar包部署的时间遇见了一个问题&#xff1a;jar中没有主属性清单&#xff0c;对此也是比较疑惑&#xff0c;在百度之后找到了解决方式 主属性清单是jar包中MANIFEST.MF文件中…

【图示化】SQL Server概念:超键(码)、候选键(候选码)、主键(主码)、主属性与非主属性、外键

关系模型概念 字段属性名&#xff0c;每一行就是一条记录一个元组&#xff0c;每个单元格就是一个分量&#xff0c; 主键&#xff0c;外键 主码主键主关键字 超键&#xff08;码&#xff09;&#xff0c;候选键 码超键 超键 &#xff08;唯一的&#xff0c;可多余&#xff09; …

候选码、主码、全码、外码、主属性、主键、主关键字、非主属性

一、讲解 首先说明 键字码字&#xff0c;所以 主键主码主关键字&#xff0c;候选键候选码候选关键字… 所谓关系键&#xff0c;指的是一个表中的一个&#xff08;或一组&#xff09;属性&#xff0c;用来标识该表的每一行或与另一个表产生联系。 话不多说&#xff0c;上图&a…

软考系列之候选码,主码,主属性,非主属性详讲

候选码&#xff0c;主码&#xff0c;主属性&#xff0c;非主属性详讲 文章目录 目录 文章目录 前言 一、候选码&#xff0c;主码&#xff0c;属性&#xff0c;非主属性的定义 二、具体题目 三、补充 前言 软考刷题&#xff0c;遇到这系列的题目&#xff0c;对我来讲&#xff0…

数据库中主键、主码、主属性、关键字、候选关键字、码的区别

码是数据库系统中的基本概念&#xff0c;所谓码就是能唯一标识实体的属性&#xff0c;它是整个实体集的性质&#xff0c;而不是单个实体的性质。它包括超码、候选码和主码。 &#xff08;1&#xff09;超码是一个或多个属性的集合&#xff0c;这些属性可以让我们在一个实体集中…

函数依赖 主码 主属性 非主属性 候选键 超键 详解

最近做项目要搞数据库看到范式那一节头脑发晕&#xff0c;概念都忘了&#xff0c;于是从网上搜罗并整理一下&#xff1b; 函数依赖部分参考&#xff1a;https://blog.csdn.net/jsj13263690918/article/details/79796275 主码&#xff1a;主关键字&#xff08;主键&#xff0c;…

c语言memset详解

目录 1 函数声明1.1功能1.2 例子 2 常见错误2.1 搞反了 ch 和 n 的位置.2.2 过度使用memset2.3 3 特殊例子 1 函数声明 void *memset(void *s, char ch, unsigned n);1.1功能 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值。块的大小由第三个参数指定,作…

【Java基础知识 9】序列化与反序列化

🍅 Java学习路线:搬砖工逆袭Java架构师 🍅 简介:Java领域优质创作者🏆、CSDN哪吒公众号作者✌ 、Java架构师奋斗者💪 🍅 扫描主页左侧二维码,加入群聊,一起学习、一起进步 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 面试官:兄弟,说说你对transient的理解和感悟 …

详解序列化与反序列化

一、什么是序列化与反序列化 序列化时将对象状态转换为可保持或传输的形式的过程。序列化的补集是反序列化&#xff0c;反序列化是将流转换为对象。两个过程一起保证能够存储和传输数据。 .NET具有以下三种序列化技术&#xff1a; 1.二进制序列化 保持类型保真&#xff0c;这…

为什么要序列化?序列化你知道哪些?

凡事都要问为什么&#xff0c;在讲解序列化概念和原理前&#xff0c;我们先来了解一下为什么需要序列化。 为什么要序列化&#xff1f; 如果光看定义我想你很难一下子理解序列化的意义&#xff0c;那么我们可以从另一个角度来感受一下什么是序列化。 都玩过游戏么&#xff1…

说说什么是序列化,如何实现序列化

分析&回答 序列化机制 序列化机制&#xff08;包括序列化和反序列化&#xff09;的本质是用流将对象读到内存和写入外存。序列化机制的意义就是将对象脱离程序运行独立存在。通过网路或跨平台传输对象&#xff0c;传递的参数与返回值都实现序列化机制。实现序列化需要实现…

java序列化详解

一、序列化与反序列化 序列化&#xff1a;指堆内存中的java对象数据&#xff0c;通过某种方式把对存储到磁盘文件中&#xff0c;或者传递给其他网络节点&#xff08;网络传输&#xff09;。这个过程称为序列化&#xff0c;通常是指将数据结构或对象转化成二进制的过程。 即将对…