既然內插搜尋法是改良自二分搜尋法,那麼實際的差異在哪呢?首先,內插搜尋法將資料的分布假設為一條直線:
若是一串資料於索引值 Ilow 與 Iupper 的值分別為 Klow 與 Kupper。假設我們需要找的目標值為 K,且 K 的索引值 I,則我們理應可以推得:(Kupper - Klow) / (Iupper - Ilow) = (K - Klow) / (I - Ilow)。
若整理以上的算式,便可以得到公式:I = Ilow + (Iupper - Ilow)(K - Klow) / Kupper - Klow。
舉例來說,現在我們需要在下面這些資料中搜尋數值 44:
5 12 19 26 37 44 60 65 73 85
則 I = 1 + [(10 - 1)(44 - 5) / (85 - 5)] = 5:
5 12 19 26 37 44 60 65 73 85
由於 37 小於目標值,因此我們對後面的資料進行同樣的搜尋,I = 6 + [(10 - 6)(44 - 44) / (85 - 44)] = 6:
5 12 19 26 37 44 60 65 73 85
發現第 I 項資料值等於搜尋值,這樣就找到欲尋找的值了。
內插搜尋法的虛擬碼大致如下:
void interpolationSearch(Type data[1..n], Type search) { Index low = 1; Index upper = n; while (low <= upper) { Index mid = low + (upper - low) * (search - data[low]) / (data[upper] - data[low]); if (data[mid] = search) { print mid; return; } else if (data[mid] > search) { upper = mid - 1; } else if (data[mid] < search) { low = mid + 1; } } print "Not found"; }
平均而言,在有 n 筆資料的情況下,內插搜尋法只需要進行 log(log(n)) 次比對就可以找到資料!可見其效率之高。
但是,在資料並非分布均勻的最差情況下,內插搜尋法則是需要進行 n 次比對才能夠找到資料。此時的效率就比二分搜尋法低得多了。
以 C 語言的實作如下:
#include <stdio.h> #include <stdlib.h> int interpolationSearch(int[], int, int); int main(void) { int search, ans; int data[] = {5, 12, 19, 26, 37, 44, 60, 65, 73, 85}; printf("請輸入欲搜尋的資料: "); scanf("%d", &search); // 呼叫函式進行搜尋 ans = interpolationSearch(data, search, sizeof(data) / sizeof(int)); if (ans < 0) { printf("找不到 %d\n", search); } else { printf("在第 %d 筆資料找到 %d\n", ans + 1, search); } system("pause"); } int interpolationSearch(int data[], int search, int n) { int low = 0, upper = n - 1; while (low <= upper) { int mid = low + (upper - low) * (search - data[low]) / (data[upper] - data[low]); if (data[mid] == search) { return mid; } else if (data[mid] > search) { upper = mid - 1; } else if (data[mid] < search) { low = mid + 1; } } return -1; }
4 回覆:
借用了您的图片和算法公式...如果不妥请留言给我哈
http://blog.gregwym.info/cs-240-fu-xi-zong-jie-zhi-liu--dictionary-tricks.html
@咳嗽di小鱼: 沒問題的, 歡迎引用
請問一下資料分布均勻的意思是已排序過嗎?
不是的,是指數字平均散佈於 I_low 至 I_upper 之間。
譬如說:13 19 25 31 37
因為在這種情況下,透過公式「猜」出來的索引值會十分接近欲找尋資料的實際索引值。
張貼留言