查找算法總結
1. 順序查找
順序查找適合於存儲結構爲順序存儲或鏈式存儲的線性表。
- 算法實現:
/**
* 順序查找的算法實現
*
* @param arr 查找的序列
* @param value 查找某個值
* @return 如果查到,返回這個值得位置下標
*/
public static int sequenceSearch(int arr[], int value) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == value) {
return i;
}
}
return -1;
}
- 算法優化:
設置這一思想,將a[0]設置成哨兵則可以避免每次比較元素後都需要判斷下標是否越界這一問題,從而節省了時間。當然,a[0]中將不能在存放有效元素
/**
* @param arr 待查找序列
* @param value 查找元素
* @return
*/
public static int sequenceSearchV2(int[] arr, int value) {
// 從後往前遍歷數組
int i = arr.length - 1;
// 將a[0]設置成哨兵,避免每次比較元素後都需要判斷下標是否越界這一問題
arr[0] = value;
// 若數組中無key,則一定會得到a[0]=key
while (arr[i] != value) {
i--;
}
//查找失敗返回0
return i;
}
2. 二分查找
元素必須是有序的,如果是無序的則要先進行排序操作。
- 算法實現:
- 非遞歸實現
/**
* 二分查找算法 - 非遞歸實現
*
* @param arr 查找的序列
* @param value 查找某個值
* @return 如果查到,返回這個值得位置下標
*/
public static int binarySearch(int[] arr, int value) {
// 定義好首尾指針
int low = 0, hign = arr.length - 1;
while (low <= hign) {
int mid = (low + hign) / 2;
if (value == arr[mid]) {
return mid;
}
if (value < arr[mid]) {
hign = mid - 1;
}
if (value > arr[mid]) {
low = mid + 1;
}
}
return -1;
}
- 遞歸實現
/**
* 二分查找算法 - 遞歸實現
*
* @param arr 查找的序列
* @param value 查找某個值
* @return 如果查到,返回這個值得位置下標
*/
public static int binarySearchV2(int[] arr, int value, int low, int hign) {
// 遞歸的終止條件1:未查詢到某個值
if (low > hign) {
return -1;
}
int mid = (low + hign) / 2;
if (value < arr[mid]) {
return binarySearchV2(arr, value, low, mid - 1);
} else if (value > arr[mid]) {
return binarySearchV2(arr, value, mid + 1, hign);
} else {
// 遞歸的終止條件2:查詢到
return mid;
}
}
3. 插值查找
- 算法思想:
基於二分查找算法,,
二分查找中查找點計算如下:mid = (low+high) / 2, 即mid = low + 1/2*(high-low);
通過類比,我們可以將查找的點改進爲如下:mid = low + (key-a[low])/(a[high]-a[low]) * (high-low),
也就是將上述的比例參數1/2改進爲自適應的,根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減少了比較次數。可以提高查找效率。當然,插值查找也屬於有序查找。
注:對於表長較大,而關鍵字分佈又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好的多。反之,數組中如果分佈非常不均勻,那麼插值查找未必是很合適的選擇。 - 算法實現:
/**
* 插值查找算法實現 - 將二分查找中的比例參數1/2改進爲自適應的
*
* @param arr 待查找序列
* @param value 查找元素
* @param low
* @param high
* @return
*/
public static int insertSearch(int[] arr, int value, int low, int high) {
if (low > high) {
return -1;
}
int mid = low + (value - arr[low]) / (arr[high] - arr[low]) * (high - low);
if (value < arr[mid]) {
return insertSearch(arr, value, low, mid - 1);
} else if (value > arr[mid]) {
return insertSearch(arr, value, mid + 1, high);
} else {
return mid;
}
}
4. 斐波那契查找
- 算法思想:
也是二分查找的一種提升算法,通過運用黃金比例的概念在數列中選擇查找點進行查找,提高查找效率。同樣地,斐波那契查找也屬於一種有序查找算法。
5. 樹表查找
-
二叉樹查找算法:
基本思想:二叉查找樹是先對待查找的數據進行生成樹,確保樹的左分支的值小於右分支的值,然後在就行和每個節點的父節點比較大小,查找最適合的範圍。 這個算法的查找效率很高,但是如果使用這種查找方法要首先創建樹。二叉查找樹(BinarySearch Tree,也叫二叉搜索樹,或稱二叉排序樹Binary Sort Tree)或者是一棵空樹,或者是具有下列性質的二叉樹:
1)若任意節點的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
2)若任意節點的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
3)任意節點的左、右子樹也分別爲二叉查找樹。
6. 分塊查找
- 算法思想:
分塊查找又稱索引順序查找,它是順序查找的一種改進方法。
將n個數據元素”按塊有序”劃分爲m塊(m ≤ n)。每一塊中的結點不必有序,但塊與塊之間必須”按塊有序”;即第1塊中任一元素的關鍵字都必須小於第2塊中任一元素的關鍵字;而第2塊中任一元素又都必須小於第3塊中的任一元素,……
7. 哈希查找
散列表(Hash table,也叫哈希表),是根據鍵(Key)而直接訪問在內存存儲位置的數據結構。也就是說,它通過計算一個關於鍵值的函數,將所需查詢的數據映射到表中一個位置來訪問記錄,這加快了查找速度。這個映射函數稱做散列函數,存放記錄的數組稱做散列表。
散列函數的規則是:通過某種轉換關係,使關鍵字適度的分散到指定大小的的順序結構中,越分散,則以後查找的時間複雜度越小,空間複雜度越高。
- 直接定址法:
取關鍵字或關鍵字的某個線性函數值爲散列地址。即hash(k) = k 或 hash(k) = a · k + b,其中a、b爲常數(這種散列函數叫做自身函數) - 數字分析法:
- 平方取中法:
- 摺疊法:
- 隨機數法:
- 除留餘數法:
- 拉鍊法:
(未完待續。。。)
參考資料
https://blog.csdn.net/yimixgg/article/details/88900038
https://www.cnblogs.com/magic-sea/p/11395997.html