一、查詢技術分類
1、靜態查詢表技術(順序查詢、二分查詢、分塊查詢)
2、動態查詢表技術(二叉查詢樹)
3、雜湊表技術(雜湊表技術)
二、查詢技術說明
衡量查詢演算法優劣的標準——平均搜尋長度(asl)=,其中ci為查詢第
i個數需要進行比較的次數(比如開始對比乙個陣列中的第
i個數,則前面已經對比了
i-1個數字),
pi表示查詢第
i個數的概率(一般會平均,即
1/n)。
a、靜態查詢表技術
1、順序查詢
(1)平均查詢長度為:(n+1)/2,即時間複雜度為o(n)。
2、二分查詢
(1)必須是有序表,而且只適用於順序儲存結構;效能只有在均勻分布的時候才是最優的。
(2)查詢長度:每經過一次比較,查詢範圍都要縮小一半,因此最大查詢長度為msl=[log2 n]+1。當
n足夠大時,可近似的表示為
log2(n)
,即時間複雜度為o(log2(n))。
(3)二分查詢要求查詢表按關鍵字有序,而排序是一種很費時的運算;而且二分查詢法要求表是順序儲存的,為保持表的有序性,在進行插入和刪除操作時,都必須移動大量記錄。因此,二分查詢的高查詢效率是以犧牲排序為代價的,它特別適合於一經建立就很少移動、而又經常需要查詢的線性表。
(4)**示例
//k為待查詢的數字,r為資料集合,函式返回k在r中的位置
int binsearch(int r, int k)
if (find)
return (mid); /*查詢成功,返回找到的元素位置*/
else
return (-1); /*查詢失敗,返回-1*/
}
3、分塊查詢(索引順序查詢)
(1)分塊查詢要求把線性表分成若干塊,塊與塊之間必須有序(即假如公升序排列,那麼第一塊的最大值,必須小於第二塊的最小值),但是在每一塊中記錄的關鍵字不一定有序。假設這種排序是按關鍵字值遞增排序的,抽取各塊中的最大關鍵字及該塊的起始位置構成乙個索引表,按塊的順序存放在乙個陣列中,顯然這個陣列是有序的。
(2)分塊查詢過程分兩步進行:
a、首先查詢索引表,確定待查記錄所在塊(可用二分查詢法或順序查詢法);
b、在相應塊(子表)中用順序查詢法查詢記錄。
(3)分塊查詢的效率介於順序查詢和折半查詢之間,對於資料量巨大的線性表,它是一種較好的方法。在表中插入或刪除乙個記錄時,只要找到該記錄所屬的塊,就可以在該塊內進行插入和刪除運算,插入和刪除無需移動大量記錄。分塊查詢的主要代價是:需要增加乙個輔助陣列的儲存空間和將初始表分塊排序的運算。
(4)**示例:
struct idtable
;struct idtable id[b]; /*b為塊數*/
int blksearch(int r, struct idtable id, int k)
/*查詢完畢,low1存放找到的塊號*/
if (low1 < b)
else /*若low1>=b,則k大於查詢表r中的所有關鍵字*/
return -1;
b、動態查詢表技術
c、雜湊表技術
1、雜湊表的定義
雜湊表是通過關鍵字進行某種計算(對映)來確定該記錄的儲存位置的一種查詢表。
2、衝突解決方法
不同的關鍵字,根據雜湊函式被對映到同乙個儲存位址,這種現象被稱為衝突。衝突是不可避免的,因為關鍵字的取值集合遠遠大於表空間的位址集合,我們只能儘量減少衝突的發生。在構造雜湊函式時,主要面臨兩個問題:一是構造較好的雜湊函式,把關鍵字集合中元素盡可能均勻地分布到位址空間中去,減少衝突的發生,另乙個就是找到解決衝突的方法。
解決衝突的方法中比較常用的是
3、雜湊演算法的過程:首先得建立雜湊表(一般都有從檔案中讀取吧?),其次才是查詢。
4、完整**示例:
#include#includestruct keynum
;struct keynum* hash[100];
struct keynum* inserthash(struct keynum*, int m);//關鍵字插入鍊錶
int searchhash(struct keynum*, int m);//查詢鍊錶中是否存在值為m的整數
void print(struct keynum*);//列印鍊錶
void main()
fscanf(p, "%d", &num);第乙個值為關鍵字的個數,因此num讀入的是關鍵字的個數,這裡預設num小於100的
for (i = 0; ikey = m;
p1 = head;
p0 = temp;//要插入的節點(值為m);
if (head == null)//1,原來的鍊錶為空,插入到head後
else//原來的鍊錶不為空
if (p0->key <= p1->key)
else//4,插入到結尾處
}return(head);
}int searchhash(struct keynum*head, int m)//查詢鍊錶head中是否存在m
p = p->next;
} while (p != null);
return(k);//存在m值則返回1,否則返回0;
}void print(struct keynum*head)//列印鍊錶head
while (p != null);
} else
printf("null");}/*
struct keynum * inserthash(struct keynum*head, int k)//
else//如果不是,則在原來的鏈條的尾巴上新增新的節點(上面已經建立好的節點)
//具體的實現方法,就是將head指標指向剛才所建立的結構體空間?(no):head並不是指向尾巴節點的指標,而是整個鏈條的首指標!!!!
return head;
}*/
總結:(1)順序查詢的查詢效率很低;但是對於待查記錄的儲存結構沒有任何要求,既適用於順序儲存,又適用於鏈式儲存;當待查表中的記錄個數較少時,採用順序查詢法較好。
(2)折半查詢的平均查詢長度較小,查詢速度快;但它只能用於順序儲存,不能用於鏈式儲存;且要求表中的記錄是有序的。對於不常變動的有序表,採用折半查詢法是較為理想的。
(3)分塊查詢的平均查詢長度介於順序查詢和折半查詢之間;跟順序查詢一樣,對記錄的儲存結構沒什麼要求,既可以用於順序儲存,也可用於鏈式儲存;要求表中元素是逐段有序的,即塊與塊之間的記錄按關鍵字有序。當待查表的資料量較大時,分塊查詢的優越性更為突出。
(4)雜湊法是一種直接計算位址的方法,通過對關鍵字值進行某種運算來確定待查記錄的儲存位址。在查詢過程中不需要進行比較,因此,其查詢時間與表中記錄的個數無關。當所選擇的雜湊函式能得到均勻的位址分布時,其查詢效率比前面的三種方法都要快。雜湊法的查詢效率取決於以下三個因素:雜湊函式、處理衝突的方法及裝填因子。
p.s.線性表包括順序儲存表(比如陣列)、鏈式儲存表(鍊錶)。
另外在程式設計的過程中,也體會到了以下內容:指向結構體的指標p或者head,無論是通過賦值還是開創的空間的強制轉換,head->next,p->next都是p結構體內next。
查詢演算法總結
順序查詢演算法 1.演算法描述 順序比較即可。2.平均查詢長度 n 1 2,其中n為表長。3.演算法實現 省略4.優化思想 根據經驗,目前被查到越多的元素,將來可能被查到的可能性也越大。所以可以考慮,每次查詢到乙個元素後,將它和直接前驅交換位置。如果上述的經驗從概率上來講是成立的,則可以加快順序查詢...
查詢演算法總結
順序查詢演算法 1.演算法描述 順序比較即可。2.平均查詢長度 n 1 2,其中n為表長。3.演算法實現 省略4.優化思想 根據經驗,目前被查到越多的元素,將來可能被查到的可能性也越大。所以可以考慮,每次查詢到乙個元素後,將它和直接前驅交換位置。如果上述的經驗從概率上來講是成立的,則可以加快順序查詢...
查詢演算法總結
一 順序查詢 二 二分查詢 int binarysearchrecursion int arry,int value,int start,int end else int binarysearchrecursion int arry,int len,int value int binarysearc...