查找表(search table)是由同一类型的数据元素(或记录)构成的集合。
对查找表进行的操作有:
(1)查询某个“特定的”数据元素是否存在查找表中。
(2)检索某个“特定的”数据元素的各种属性。
(3)在查找表中插入一个数据元素。
(4)从查找表中删除某个数据元素。
只做查询的操作的查找表称为静态查找表(Static Search Table)。
若在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已存在的某个数据元素,则称此查找表为动态查找表(Dynamic Search Table)。
关键字(Key)是数据元素(或记录)中某个数据项的值,用它可以标识一个数据元素(或记录),若此关键字可以唯一的标识一条记录,则称此关键字为主关键字(Primary Key),其他的用于识别若干记录的关键字称为次关键字(Secondary Key)。当数据元素只有一个数据项时,其关键字即为该数据元素的值。
查找(Searching)根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录或数据元素。若表中存在这样的记录,则查找是成功的,若不存在,则查找不成功,给出“空”记录或空指针。
典型的关键字类型说明可以是:
typedef float KeyType; //实型
typedef int KeyType; //整型
typedef char *KeyType; //字符型
数据元素类型定义为:
typedef struct{
KeyType key; //关键字域
... //其他
}
对两个关键字的比较的宏定义如下:
//--对数值型关键字
#define EQ(a,b) ((a) == (b))
#define LT(a,b) ((a) < (b))
#define LQ(a,b) ((a) <= (b))
...
//--对字符型关键字
#define EQ(a,b) (!strcmp((a),(b)))
#define LT(a,b) (strcmp((a),(b)) < 0)
#define LQ(a,b) (strcmp((a),(b)) <= 0)
1 静态查找表
抽象数据类型静态查找表定义如下:
ADT StaticSearchTable{
数据对象D:D是具有相同特性的数据元素的集合,各个数据元素均含有类型相同的,可唯一标识数据元素的关键字。
数据关系R:数据元素同属一个集合。
基本操作P:
Create(&ST,n);
操作结构:构造一个含n个数据元素的静态查找表ST。
Destroy(&ST);
初始条件:静态查找表ST存在。
操作结果:销毁表ST。
Search(ST,key);
初始条件:静态茶渣表ST存在,key为和关键字类型相同的给定值。
操作结果:若ST中存在其关键字等于key的数据元素,则函数值为该元素的值或在表中的位置,否则为“空”。
Traverse(ST,visit());
初始条件:静态查找表ST存在,visit是对元素操作的应用函数。
操作结果:按某种次序对ST的每隔元素调用函数visit()一次。
}ADT StaticSearchTable;
1.1 顺序表的查找
//----------- 静态查找表的顺序存储结构------------
typedef struct{
Element *elem;//数据元素存储空间基址
int length;
}SSTable;
顺序查找表的实现(Sequential Search):
从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较成功,则查找成功,反之,直到第一个记录,仍不能成功比较,则查找不成功。
int search_seq(SSTable ST,KeyType key){
int i;
//在顺序表ST中顺序查找其关键字=key的数据元素,
//若找到,则函数值为该元素在表中的位置,否则为0.
ST.elem[0].key = key;//哨兵
for(i=ST.length;!ST.item[i].key == key;--i) //从后往前找
return i; //找不到时,i =0
}//search_seq
查找操作的性能分析:
衡量一个算法好坏的量度有3条:
时间复杂度
空间复杂度(衡量算法的数据结构所占存储以及大量的附加存储)
算法的其他性能
通常以”其关键字和给定值进行过比较的记录个数的平均值“作为衡量查找算法好坏的依据。
平均查找长度(Average Search Length):为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望。
(1) 等概率的情况下顺序查找成功的平均查找长度为:
(n+1)/2
(2) 查找不成功的平均查找长度为
n+1
(3) 当查找不成功的概率不可以忽略时,假设查找成功和查找不成功的概率相同,则顺序查找的平均查找长度为:
3(n+1)/4
顺序查找的缺点:当n较大时,查找效率很低。
1.2 有序表的查找
折半查找(Binary Search):先确定待查记录所在的范围,然后逐步缩小范围直到找到或找不到记录为止。
顺序查找的查找过程如下:
(1) 确定待查记录所在的范围,设区间范围为[low,high];
(2) 求出处于该区间中间位置的值mid,mid = [low+high]/2;
(3) 将给定的key值与有序表中第mid个记录的关键字ST.item[mid].key相比较
(3.1) 若key == ST.item[mid].key,则查找成功
(3.2) 若key < ST.item[mid].key,则high=mid-1,并判断high是否小于low,若high<low,则查找不成功,否则,待查记录还是可能在新的区间[low,high]中,继续执行步骤(2)
(3.3) 若key > ST.item[mid].key,则low = mid + 1,判断high是否小于low,若high<low,则查找不成功,否则,待查记录还是可能在新的区间[low,high]中,继续执行步骤(2)。
算法实现如下:
int binarySearch(STable ST,KeyType key){
int mid,low=0,high=ST.length;
while(low <=high){
mid = (low+high)/2;
if(ST.item[mid].key == key) return mid;
elseif(ST.item[mid].key < key) low = mid + 1;
else high = mid - 1;
}
return 0;
}
折半查找的过程可以用二叉树表示,
判定树即描述查找过程的二叉树
折半查找时与给定值进行比较的次数最多为[log(2)n]+1次
(1) 查找成功时的平均查找长度:
ASL = (n+1)/n * log(2)(n+1) - 1
当n>50时,简化为
ASL = log(2)(n+1)-1
(2) 查找不成功时的平均查找长度
uASL = log(2)(n+1)
折半查找的优点:查找效率比顺序查找的高
缺点:只能适用于有序表,且顺序存储结构,不能用于线性链表
1.3 索引顺序表的查找
索引顺序表包括存储数据的顺序表(称为主表)和索引表两部分。顺序表被分为若干子表(又称块),整个顺序表有序或分块有序。将每个子表中的最大关键字取出,再加上指向该关键字记录所在子表第一个元素的指针,就构成一个索引项,将这些索引项按关键字增序排列,就构成了索引表。
对于索引顺序表可按分块进行查找,过程分为两个阶段:
(1) 确定待查记录所在的子表(块),由于索引表是按关键字有序排列的,对于索引表可按折半查找,若待查记录关键字的key值,<=第i个子表最大关键字,且大于第i-1个子表的最大关键字,即K(i-1) < key < K(i),则待查关键字位于第i个子表中。
(2) 在已确定的子表中确定待查记录的位置,由于子表中的记录不一定按关键字有序排列,只能按顺序查找法查找。
索引表类型定义如下:
#define MAXLEN <索引表最大长度>
typedef int keytype;
typedef struct{
keytype key;
int link;
}IndexType;//索引项数据类型
typedef IndexType IDX[MAXLEN+1];//索引表类型,下标从1开始
索引表查找算法:
IndxSearch(IDX idx,int b,STable,keytype key){
int s = ST.length / b; //b为索引表中元素个数,s为每个子表中元素个数
int i,j;
for(i=1;i<b+1;i++)
if(key <= idx[i]) break;
if(i == b+1) return 0;//从索引表中查找失败
//注意,此处是从idx[i].link开始,不能设置0哨兵,只能用if判断j == idx[i].link-1
for(j = idx[i].link+s-1;key!=ST.item[j].key;j--);
if(j == idx[i].link-1) return 0;
else return j;
}
一般情况下,为进行分块查找,可以将长度为n的表均匀分成b块,每块还有s个元素,即b = [n/s],如果索引表采用顺序查找的方式,则查找成功时的平均查找长度为:
(s+b+2)/2
如果索引表采用折半查找,则成功时的平均查找长度为:
log(2)(n/s+1)+s/2
分享到:
相关推荐
在本课程设计中,我们将关注一种特定的数据查找方法——索引顺序查找,这是一种结合了顺序查找和索引查找优势的算法。在这个项目中,我们使用C++编程语言来实现这一算法。 首先,让我们理解什么是索引顺序查找。...
**索引顺序表查找**是一种在数据...通过结合索引查找和顺序查找,它能够在保持较低复杂度的同时,避免完全依赖高级查找算法带来的额外开销。在实际编程中,理解并熟练掌握这种查找策略对于优化程序性能具有重要意义。
3. **查找索引**:接下来,程序通过遍历索引表来确定待查找元素可能位于哪个区间。具体步骤如下: - 遍历索引表,找到第一个满足 `a > stable[i].stelem` 的索引 `i`。 - 如果找到了这样的索引,则进一步计算具体...
平均查找长度(ASL)计算公式为:ASL = ASLb + ASLe,其中ASLb是索引查找的平均查找长度,ASLe是块内顺序查找的平均查找长度。在分块查找中,平均查找长度通常介于顺序查找和折半查找之间,当块大小s取为sqrt(n)时,...
2. **索引查找**: 使用索引表快速定位到可能包含目标元素的子区间。 3. **顺序查找**: 在定位到的子区间内执行顺序查找,直到找到目标元素或确认不存在。 示例代码如下所示: ```c #include // 定义数据表 int ...
这里我们聚焦于四个关键概念:顺序查找表、二分查找表(也称折半查找表)、二叉排序树以及C#编程语言。这些知识点在计算机科学和软件工程中都有着广泛的应用。 1. **顺序查找表**: 顺序查找是最基础的查找方法,...
在本主题中,我们将聚焦于两种基础但重要的查找算法:顺序查找和折半查找。 **顺序查找(Sequential Search)** 顺序查找是最简单的查找算法,适用于任何线性数据结构,如数组或链表。其基本思想是从数据集合的第一...
在实际应用中,静态查找表可能采用一些优化策略,比如哈希表,通过哈希函数将键值映射到数组索引,可以进一步提高查找速度,达到近乎常数时间的平均查找复杂度。但是,哈希表并不是真正的静态查找表,因为它通常允许...
在含有n个元素的顺序表中,顺序查找的策略是从头到尾逐个比较,直到找到目标元素或者遍历完整个列表。在最坏的情况下,顺序查找需要比较n次才能确定元素不存在,而在最好的情况下(即元素位于列表首位),只需比较一...
本文将详细探讨四种常见的查找算法:顺序查找、折半查找、二叉排序树查找以及哈希表查找,并结合提供的"综合查找算法"课程设计项目,解析其在实际应用中的特点和优势。 **顺序查找**是最基础的查找算法,适用于任何...
顺序查找和二分查找是两种常见的数据查找方法,在计算机科学中有着广泛的应用。这两种方法都是在数组或列表中寻找特定元素的过程,但它们的效率和实现方式有所不同。 **顺序查找**: 顺序查找是最基础的查找算法,...
实验七的主题是“查找”,主要涉及查找表、动态查找表、静态查找表和平均查找长度的概念,以及线性表中的顺序查找和折半查找方法。此外,还要求掌握哈希函数的构造、处理冲突的机制和哈希表的查找。 1. **查找表**...
下面,我们将介绍四种常见的查找算法:顺序查找、折半查找、二叉排序树和哈希表。 顺序查找 顺序查找是最简单的一种查找算法。它的工作原理是从数据集合的开始处依次比较每个元素,直到找到目标元素或者达到集合的...
本文将详细介绍顺序表的查找和删除操作,并提供了一个使用C++编写的示例代码。 顺序表的定义 顺序表是一种线性表,元素之间是连续的,各个元素的存储地址是连续的。顺序表的每个元素都有其唯一的索引值,索引值是从...
查找操作是静态查找表的核心,常见的查找方法有顺序查找和二分查找。顺序查找是从数组的一端开始逐个比较直到找到目标元素或遍历完整个数组。虽然简单,但效率较低,特别是当数据无序时。相比之下,如果数组是有序的...
顺序查找是一种简单的搜索算法,常用于线性数据结构,如数组。在C++编程中,实现顺序查找并不复杂,但效率相对较低,特别是在大规模数据集上。本篇将详细讲解顺序查找的基本概念、C++代码实现及其应用。 顺序查找的...
"有监视哨的顺序查找"是一种在数据结构与算法领域中的搜索方法,它对传统的顺序查找进行了优化。顺序查找通常是在未排序的序列中寻找目标值,从序列的第一个元素开始,逐个比较直到找到目标或者遍历完整个序列。而...
二分查找索引表,在索引表中定块采用顺序方法进行查找