More Related Content More from Wang Yizhe (12) 第九章 查找[1]2. 查找 Searching
• 在日常生活中 , 人们每天都要进行”
查找”工作 . 在各种系统软件或应用
软件中 , 查找表是最为常见的数据结
构.
• “ 查找”即为在一个含有众多的数据
元素 ( 或记录 ) 的查找表中找出某个
”特定”数据元素 ( 或记录 ).
3. 何谓查找表 ?
查找表 (Search Table) 是由同一类
型的数据元素 ( 或记录 ) 构成的集合
。
由于 “ 集合 ” 中的数据元素之间存
在着松散的关系,因此查找表是一
种应用灵便的结构。
6. 关键字 Key
是数据元素(或记录)中某个数
据项的值,用以标识(识别)一
个数据元素(或记录)。
若此关键字可以识别唯一的一个记
录,则称之谓“ 主关键字 ” (Primary
Key) 。
若此关键字能识别若干记录,则称
之谓“ 次关键字 ” (Secondary Key) 。
7. 查找
根据给定的某个值,在查找表中确
定一个其关键字等于给定值的数据元素或
(记录)。
若查找表中存在这样一个记录,则称“查
找成功”。查找结果给出整个记录的信息,或指
示该记录在查找表中的位置;
否则称“查找不成功”。查找结果给出
“ 空记录”或“空指针”。
8. 如何进行查找?
在一个结构中查找某个数据元
素的过程依赖于这个数据元素在结构中所
处的地位 . 因此 , 对表进行查找的方法取决
于表中数据元素依何种关系组织在一起的
. 如电话号码本按照用户的名称分类且依
笔画顺序编排 , 则查找的方法就是先顺序
查找待查用户的类别 , 然后在类中顺序查
找 , 直到找到该用户的电话号码 .
13. 基本操作 P :
Create(&ST, n);
Destroy(&ST);
Search(ST, key);
Traverse(ST, Visit());
} ADT StaticSearchTable
20. 一、顺序查找表
以顺序表或线性链表表示静态查找表
回顾顺序表的查找过程:
k=1 k=7
ST.elem
21 37 88 19 92 05 64 56 80 75 13
0 1 2 3 4 5 6 7 8 9 10 11
ST.Length
假设给定值 e=64, 要求 ST.elem[k] = e, 问 : k = ?
21. 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
22. 顺序查找 (Sequential Search) 的实
现
• 从表中最后一个记录开始 , 逐个进行
记录的关键字和给定值的比较 . 若比
较的结果相等 , 则查找成功 . 否则 , 查
找过程直至第一个记录 , 关键字和给
定值比较均不等 , 则表明表中没有所
查记录 , 查找不成功 .
23. i i
ST.elem
64 21 37 88 19 92 05 64 56 80 75 13
0 1 2 3 4 5 6 7 8 9 10 11
key=64 ST.Length
i i
ST.elem
60 21 37 88 19 92 05 64 56 80 75 13
0 1 2 3 4 5 6 7 8 9 10 11
key=60 ST.Length
24. 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
25. 分析顺序查找的时间性能
定义: 查找算法的 平均查找长度
(Average Search Length)
为确定记录在查找表中的位置,需和给定值
进行比较的关键字个数的期望值
n
ASL = ∑ Pi Ci
i =1
: n 为表长, Pi 为查找表中第 i 个记录的概率,
n
∑
且 1 Pi = 1
i=
, Ci 为找到该记录时,曾和
值比较过的关键字的个数。
26. 对顺序表而言, Ci = n-i+1
ASL = nP1 +(n-1)P2 + +2Pn-1+Pn
1
在等概率查找的情况下,
Pi =
n
顺序表查找的平均查找长度为:
n
1 n +1
ASL ss = ∑ (n − i + 1) =
n i =1 2
27. 在不等概率查找的情况下, ASLss 在
Pn≥ Pn-1≥ · · · ≥ P2≥ P1
时取极小值 .
即因为排在查找表尾部 ( i=n) 的
对象所需比较的次数最少 , 因此将对象按
照出现概率从小到大的顺序排列 , 可使平
均查找长度 A S L s s 极小 .
29. 二、有序查找表
若以有序表表示静态查找表,
则查找过程可以基于 “ 折半” 进行。
折半查找 (Binary Search) 的查找过程 :
先确定待查记录所在的范围 ( 区
间 ), 然后逐步缩小范围直到找到或找
不到该记录为止 .
30. 例如 : key=64 的查找过程如下:
ST.length
ST.elem
05 13 19 21 37 56 64 75 80 88 92
0 1 2 3 4 5 6 7 8 9 10 11
low low high high
mid mid mid
low 指示查找区间的下界
high 指示查找区间的上界
mid = (low+high)/2
31. int Search_Bin ( SSTable ST, KeyType key ) {
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
32. 分析折半查找的平均查找长度
先看一个具体的情况,假设: n=11
i 1 2 3 4 5 6 7 8 9 10 11
Ci 3 4 2 3 4 1 3 4 2 3 4
从查找过程看出 , 找位置 6 的
元素需比较 1 次 , 找位置 3 和 9 的元
素需比较 2 次 , 找位置 1,4,7,10 的元素
需比较 3 次 , 找位置 2,5,8,11 的元素需
比较 4 次
33. 分析折半查找的平均查找长度
整个查找过程可以用一棵二叉树来
描述 . 例如 , 若找结点 A, 则整个查找过程
为走了一条从根到 A 的路径 6-9-10.
判定树 6
3 9
1 4 7 10
2 5 8 A 11
34. 判定树 6
3 9
1 4 7 10
2 5 8 A 11
一般情况下,表长为 n 的折半查找的
判定树的深度和含有 n 个结点的完全二叉树的深
度相同 h=log2(n+1) 。树中层次为 1 的结点有 1 个 ,
层次为 2 的结点为 2 个 ..., 则层次为 h 的结点数则
为 2h-1 个 .
35. 分析折半查找的平均查找长度
设 n=2h-1 并且查找概率相等
1 n 1 h j −1 n+1
则 ASLbs = ∑ Ci = ∑ j × 2 = log 2 (n + 1) − 1
n i =1 n j =1 n
j 为层数且等于搜
在 n>50 时,可得近似结果 j 层元素的比较
寻
次数 , 2 j- 1 为 j 层的
ASL ≈ log (n + 1) − 1
bs 2 元素个数 .
折半查找的效率比顺序查找高 , 但折半查找只适
用于有序表且限于顺序存储结构 .
40. 例如 i
: 索引表
最大关键字 22 48 86
起始地址 1 7 13
22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 49 86 53
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
j
key=38 找到 ST.elem[10].key = 38
key=29 未找到
41. 查找步骤与策略
查找过程分两步 , 先确定待
查记录所在的子表 , 然后在块中顺序查
找.
* 索引表按关键字有序 , 则确定块的查
找可以用顺序查找或折半查找 .
* 块中记录任意排列 , 采用顺序查找 .
43. 设 : 表的长度: n 。均匀分成的块数: b ,每块
记录个数: s n s b =
,即 . 设 : 每个记录的查
找概率相等,则每块查找的概率 : 1/b ,块中每个
记录的查找概率 : 1/s .
若用顺序查找确定所在的块,则:
1 b 1 s b +1 s +1 1 n
ASLbs = Lb + Lw= ∑ j + ∑ i = + = ( + s) + 1
b j =1 s i =1 2 2 2 s
平均查找长度不仅与表长 n 有关还与每块中的记录个数
s 有关 . 可以证明 :
当 s= n 时, ASLbs 最小 =
n +1
这个值比顺序查找有很大改进 , 但不如折半查找 .