9.1 查找表:静态查找表.
9.2 查找表:动态查找表.
9.3 查找表:哈希表.
9.1 查找表:静态查找表
1 基本概念
查找表(Search Table)是由同一类型的数据元素(或记录)构成的集合。
对查找表经常进行的操作:
1)查询
某个特定的
数据元素是否在查找表中。
2)检索
某个特定的
数据元素的各种属性。
3)在查找表中插入
一个数据元素。
4)从查找表中删去
某个数据元素。
静态查找表
(Static Search Table):仅做 “查询”、“检索” 操作的查找表。
动态查找表
(Dynamic Search Table):查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已存在的某个数据元素的查找表。
查找:
根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素或(记录)。
若查找表中存在这样一个记录,则称“查找成功
”,查找结果:给出整个记录的信息,或指示该记录在查找表中的位置;
否则称“查找不成功
”,查找结果:给出“空记录”或“空指针”。
关键字:
是数据元素(或记录)中某个数据项的值,用以标识(识别)一个数据元素(或记录)。
若此关键字可以识别唯一的一个记录,则称之谓“主关键字"。
若此关键字能识别若干记录,则称之谓“次关键字”。
以后各节的讨论中,涉及的关键字类型和数据元素类型统一说明如下:
典型的关键字类型说明可以是
typedef float KeyType; //实型
typedef int KeyType; //整型
typedef char *KeyType; //字符串型
数据元素类型定义为:
typedef struct {
KeyType key; //关键字域
... //其他域
}SElemType;
对两个关键字的比较约定为如下的宏定义:
//--对数值型关键字
#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)
int strcmp(const char* str1,const char* str2);
返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。
如何进行查找?
取决于查找表的结构。
然而,查找表本身是一种很松散的结构,因此,为了提高查找的效率,需要在查找表中的元素之间人为地附加某种确定的关系。换句话说,用另外一种结构来表示查找表。
2 抽象数据类型
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()一次且仅一次。一旦Visit()失败,则操作失败。
} ADT StaticSearchTable
假设静态查找表的顺序存储结构
为
typedef struct {
ElemType *elem; //数据元素存储空间基址,建表时按实际长度分配, 0号单元留空
int length; //表的长度
} SSTable;
3 顺序查找表
以顺序表或线性链表表示静态查找表
3.1 顺序存储结构模块中的实现
int Location(SqList L, ElemType &e, Status (* compare)(ElemType, ElemType)){
k = 1;
p = L.elem;
while(k<=L.length && !(*compare)(*p++,e)){
k++;
}
if(k<=L.length){
return k;
}else{
return 0;
}
}//Location
以上查找过程中每一步都需要检测整个表是否查找完毕。
现优化如下:
int Search_Seq(SSTable ST, KeyType key){
//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0.
ST.elem[0].key = key; //哨兵
for(i=ST.length; ST.elem[i].key!=key, --i); //从后往前找
return i; //找不到时, i为0
}//Search_Seq
3.2 分析顺序查找的时间性能.
平均查找长度定义:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值称为查找算法在查找成功时的
平均查找长度
(Average Search Length)。
对于含有n个记录的表,查找成功时的平均查找长度为
A
S
L
=
∑
i
=
1
n
P
i
C
i
ASL=\displaystyle\sum_{i=1}^{n}P_{i}C_{i}
ASL=i=1∑nPiCi 。
其中:
n 为表长。
P
i
P_{i}
Pi 为查找表中第i个记录的概率,且
∑
i
=
1
n
P
i
=
1
\displaystyle\sum_{i=1}^{n}P_{i}=1
i=1∑nPi=1 。
C
i
C_{i}
Ci 为找到表中其关键字与给定值相等的第i个记录时,和给定值已进行过比较的关键字个数。显然,
C
i
C_{i}
Ci 随查找过程不同而不同。
若查找概率无法事先测定,则查找过程采取的改进办法是,在每次查找之后,将刚刚查找到的记录直接移歪表尾的位置上。
4 有序查找表
上述顺序查找表的查找算法简单,但平均查找长度较大,特别不适用于表长较大的查找表。
4.1 代码实现
//折半查找
int Search_Bin(SSTable ST, KeyType key){
//在有序表ST中折半查找其关键字等于key的数据元素。
//若找到,则函数值为该元素在表中的位置,否则为0。
low = 1;
high = ST.length;//置区间初值
while(low <= high) {
mid = (low + high) / 2;
if(EQ(key, ST.elem[mid].key)){
return mid;//找到待査元素
}else if(LT(key, ST.elem[mid].key)){ //待查关键字小于 中间记录的关键字
high = mid - 1; //继续在前半区间进行查找
}else{
low = mid + 1;//继续在后半区间进行查找
}
}
return 0; //顺序表中不存在待查元素
}//Search_Bin
4.2 折半查找的平均查找长度
待整理
5 静态查找树表
待整理
6 索引顺序表
待整理
——《数据结构图 (C语言版) 严蔚敏》 学习笔记