基本概念
列表:由同一类型的数据元素(或记录)构成的集合,可利用任意数据结构实现。
关键字:数据元素的某个数据项的值,用它可以标识列表中的一个或一组数据元素。
主关键字:可以唯一标识列表中的一个数据元素的关键字,否则为次关键字。当数据元素仅有一个数据项时,数据元素的值就是关键字。
查找:
根据给定的关键字值,在特定的列表中确定一个其关键字与给定值相同的数据元素,并返回该数据元素在列表中的位置。
在查找算法中要用到三类参量,即:
①查找对象K(找什么)
②查找范围L(在哪找)
③查找的结果(K在L中的位置)
其中①、 ②为输入参量,在函数中不可缺少。③为输出参量,可用函数返回值表示,也可用指针参数。
平均查找长度:
为确定数据元素在列表中的位置,需和给定值进行比较的关键字个数的期望值。长度为n,查找成功时的平均查找长度:
顺序查找法:
特点:
用所给关键字与线性表中各元素的关键字逐个比较,直到成功或失败。
数据类型定义:
#define LIST_SIZE 20
typedef struct {
KeyType key;
OtherType other_data;
} RecordType;
typedef struct {
RecordType r[LIST_SIZE+1]; /* r[0]为工作单元 */
int length;
} RecordList;
在表一端设置“监视哨”附加单元
存放要查找的关键字,从表另一端查找,如果在监视哨找到则查找失败。
int SeqSearch(RecordList L, KeyType k)
{
L.r[0].key = k; i = L.length; //l.r[0]为监视哨,防止越界
while (L.r[i].key != k) i--;
return(i);
}
平均查找长度为(n+1)/2。
不设置监视哨的顺序查找算法:
int SeqSearch(RecordList l, KeyType k)
{
i = l.length;
while (i >= 1&& l.r[i].key !=k) i--;
if (i>=1) //i>=1判断查找是否越界
return(i)
else return (0);
}
折半查找法:
要求待查找列表 ① 用顺序存储结构;② 按关键字大小有序(从小到大)排列 。
算法思想:
① 将表中间位置记录的关键字与查找关键字比较,相等则查找成功;否则,利用中间位置记录将表分成前、后两个子表。
② 而如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
③ 重复以上过程,直到找到满足条件的记录,或直到子表不存在为止,此时查找不成功。
k < l.r[mid]:前半子表查,high = mid-1;
k > l.r[mid]:后半子表查,low = mid+1。
high<low时,查找失败。
int BinSrch(RecordList L, KeyType k)
{
low = 1; high = L.length; /*置区间初值*/
while (low <= high)
{ mid = (low + high) / 2;
if(k == L.r[mid]. key) return(mid);/*找到待查元素*/
else if (k < L.r[mid]. key) high = mid - 1;/*在前半区间进行查找*/
else low = mid + 1; /*在后半区间进行查找*/
}
return (0);
}
算法分析:
可用二叉判定树来描述,树中每个结点对应一个记录:
① 中间记录为根,前子表为左子树,后子表为右子树;
② 查找记录过程,对应树从根到对应结点的路径,比较次数为结点在树中的层次。
分块查找法:
要求将列表组织成以下索引顺序结构:
① 将列表分成若干个块(子表):
一般情况下,块的长度均匀,最后一块可以不满。每块中元素任意排列,即块内无序,但块间有序。
② 构造一个索引表:
其中每个索引项对应一个块并记录每块的起始位置,和每块中的最大关键字(或最小关键字)。索引表按关键字有序排列。
基本过程:
1)将待查关键字K与索引表中的关键字进行比较,以确定待查记录所在的块。
具体的可用顺序查找法或折半查找法进行。
2)进一步用顺序查找法,在相应块内查找关键字为K的元素。
算法分析:
分块查找的平均查找长度由两部分组成:
查找索引表时的平均查找长度为LB,
相应块内进行顺序查找的平均查找长度LW。
ASL(bs)=LB+LW
。