本節介紹一種在順序查找的基礎上對其進行改進的算法——分塊查找算法。
分塊查找,也叫索引順序查找,算法實現除了需要查找表本身之外,還需要根據查找表建立一個索引表。例如圖 1,給定一個查找表,其對應的索引表如圖所示:
圖 1 查找表及其對應的索引表
分塊有序指的是第二個子表中所有關鍵字都要大於第一個子表中的最大關鍵字,第三個子表的所有關鍵字都要大於第二個子表中的最大關鍵字,依次類推。建立的索引表要求按照關鍵字進行升序排序,查找表要么整體有序,要么分塊有序。
塊(子表)中各關鍵字的具體順序,根據各自可能會被查找到的概率而定。如果各關鍵字被查找到的概率是相等的,那么可以隨機存放;否則可按照被查找概率進行降序排序,以提高算法運行效率。
分塊查找的具體實現
所有前期准備工作完成后,開始在此基礎上進行分塊查找。分塊查找的過程分為兩步進行:- 確定要查找的關鍵字可能存在的具體塊(子表);
- 在具體的塊中進行順序查找。
以圖 1 中的查找表為例,假設要查找關鍵字 38 的具體位置。首先將 38 依次和索引表中各最大關鍵字進行比較,因為 22 < 38 < 48,所以可以確定 38 如果存在,肯定在第二個子表中。
由於索引表中顯示第二子表的起始位置在查找表的第 7 的位置上,所以從該位置開始進行順序查找,一直查找到該子表最后一個關鍵字(一般將查找表進行等分,具體子表個數根據實際情況而定)。結果在第 10 的位置上確定該關鍵字即為所找。
提示:在第一步確定塊(子表)時,由於索引表中按照關鍵字有序,所有可以采用折半查找算法。而在第二步中,由於各子表中關鍵字沒有嚴格要求有序,所以只能采用順序查找的方式。
具體實現代碼:
#include <stdio.h> #include <stdlib.h>
struct index
{
//定義塊的結構 int key; int start;
} newIndex[3]; //定義結構體數組 int search(int key, int a[]);
int cmp(const void *a,const void* b)
{ return (*(struct index*)a).key>(*(struct index*)b).key?1:-1; }
int main()
{ int i, j=-1, k, key; int a[] = {33,42,44,38,24,48, 22,12,13,8,9,20, 60,58,74,49,86,53}; //確認模塊的起始值和最大值 for (i=0; i<3; i++)
{ newIndex[i].start = j+1; //確定每個塊范圍的起始值 j += 6; for (int k=newIndex[i].start; k<=j; k++)
{ if (newIndex[i].key<a[k])
{ newIndex[i].key = a[k]; } } } //對結構體按照 key 值進行排序 qsort(newIndex,3, sizeof(newIndex[0]), cmp); //輸入要查詢的數,並調用函數進行查找 printf("請輸入您想要查找的數:\n"); scanf("%d", &key); k = search(key, a); //輸出查找的結果 if (k>0)
{ printf("查找成功!您要找的數在數組中的位置是:%d\n",k+1); }
else
{ printf("查找失敗!您要找的數不在數組中。\n"); }
return 0; }
int search(int key, int a[])
{ int i, startValue; i = 0; while (i<3 && key>newIndex[i].key)
{
// 確定在哪個塊中,遍歷每個塊,確定key在哪個塊中 i++; } if (i>=3)
{
//大於分得的塊數,則返回0 return -1; } startValue = newIndex[i].start; //startValue等於塊范圍的起始值 while (startValue <= startValue+5 && a[startValue]!=key) { startValue++; } if (startValue>startValue+5)
{
//如果大於塊范圍的結束值,則說明沒有要查找的數 return -1; }
return startValue; }
運行結果: 請輸入您想要查找的數: 22 查找成功!您要找的數在數組中的位置是:7
分塊查找的性能分析
分塊查找算法的運行效率受兩部分影響:查找塊的操作和塊內查找的操作。查找塊的操作可以采用順序查找,也可以采用折半查找(更優);塊內查找的操作采用順序查找的方式。相比於折半查找,分塊查找時間效率上更低一些;相比於順序查找,由於在子表中進行,比較的子表個數會不同程度的減少,所有分塊查找算法會更優。總體來說,分塊查找算法的效率介於順序查找和折半查找之間。
