參考鏈接 https://www.cnblogs.com/yw09041432/p/5908444.html
1.順序查找
說明:順序查找適合於存儲結構為順序存儲或鏈接存儲的線性表。
基本思想:順序查找也稱為線形查找,屬於無序查找算法。從數據結構線形表的一端開始,順序掃描,依次將掃描到的結點關鍵字與給定值k相比較,若相等則表示查找成功;若掃描結束仍沒有找到關鍵字等於k的結點,表示查找失敗。
復雜度分析:
查找成功時的平均查找長度為:(假設每個數據元素的概率相等) ASL = 1/n(1+2+3+…+n) = (n+1)/2 ;
當查找不成功時,需要n+1次比較,時間復雜度為O(n);
所以,順序查找的時間復雜度為O(n)。
1 /** 2 * 3 * @param {被查找數組} arr 4 * @param {查找的關鍵值} value 5 */ 6 function SequenceSearch(arr, value){ 7 for(let i = 0; i < arr.length; i++){ 8 if (arr[i] == value){ 9 return i; 10 } 11 } 12 return - 1; 13 }
2.二分查找
二分查找 也為折半查找
首先要找到一個中間值,通過與中間值比較,大的放又,小的放在左邊。再在兩邊中尋找中間值,持續以上操作,直到找到所在位置為止
找不到返回false
1 // 遞歸 2 function binarySearch(data, dest, start, end){
if (start > end){ // 新增否則找不到進入死循環了
return false;
} 3 var end = end || data.length - 1; 4 var start = start || 0; 5 var m = Math.floor((start + end) / 2); 6 //直接命中 7 if (data[m] == dest){ 8 return m; 9 } 10 11 12 if (data[m] > dest){ // 放左 13 end = m - 1; 14 return binarySearch(data, dest, start, end); 15 }else{ // 放右 16 start = m + 1; 17 return binarySearch(data, dest, start, end); 18 } 19 return false; 20 } 21 22 // 非遞歸 用while 23 //代碼中的判斷條件必須是while (left <= right), 24 //否則的話判斷條件不完整,比如:array[3] = {1, 3, 5}; 25 //待查找的鍵為5,此時在(low < high)條件下就會找不到,因為low和high相等時,指向元素5,但是此時條件不成立,沒有進入while()中 26 27 function binarySearch2(data, dest){ 28 var end = data.length - 1; 29 var start = 0; 30 while(start <= end){ 31 var m = Math.floor((end + 1) / 2); 32 if(data[m] == dest){ 33 return m; 34 } 35 if (data[m] > dest){ 36 end = m - 1; 37 }else{ 38 start = m + 1; 39 } 40 } 41 return false 42 }
3. 插值查找
將二分查找的點改進為 mid=low+(key-a[low])/(a[high]-a[low])*(high-low)
基本思想:基於二分查找算法,將查找點的選擇改進為自適應選擇,可以提高查找效率。當然,差值查找也屬於有序查找。
注:對於表長較大,而關鍵字分布又比較均勻的查找表來說,插值查找算法的平均性能比折半查找要好的多。反之,數組中如果分布非常不均勻,那么插值查找未必是很合適的選擇。
復雜度分析:查找成功或者失敗的時間復雜度均為O(log2(log2n))。
1 function InsertionSearch(arr, val, start, end){ 2 var end = end || data.length - 1; 3 var start = start || 0; 4 5 var mid = start + (val - arr[low]) / (arr[end] - arr[start]) * (end - start); 6 if(arr[mid] == val){ 7 return mid; 8 } 9 10 if(arr[mid] > val){ 11 return InsertionSearch(arr, val, start, mid - 1); 12 } 13 else{ 14 return InsertionSearch(arr, val, mid + 1, end); 15 } 16 }
4. 斐波那契查找
斐波那契數列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(從第三個數開始,后邊每一個數都是前兩個數的和)
1 // 斐波那契數組的實現 2 function getNum1(index){ 3 if (index == 1 || index == 2){ 4 return 1; 5 }else{ 6 return getNum(index - 1) + getNum(index - 2); 7 } 8 } 9 10 function getNum2(index){ 11 if (index == 1 || index == 2){ 12 return 1; 13 }else{ 14 var one = 1; 15 var two = 1; 16 for (var i = 3; i <= index; i++) 17 { 18 if (i == 3) 19 { 20 one = 1; 21 two = 1; 22 } 23 else 24 { 25 var temp = one; 26 one = two; 27 two = temp + two; 28 } 29 } 30 return one + two 31 } 32 } 33 34 function getNum3(index) 35 { 36 var F = []; 37 F[0]=0; 38 F[1]=1; 39 for(var i=2; i < index - 1; i++){ 40 F[i]=F[i-1]+F[i-2]; 41 } 42 return F[index]; 43 }
顧名思義,該查找方法利用了斐波那契數列
該方法的主要思路為,先在斐波那契數列F中找到第k項,使其滿足,F[k]-1 > 有序數組的最大索引號 > F[k-1]-1,然后將數組擴充到長度為F[K]-1,並使擴充項的值都等於有序數組的最后一項。
分割點的索引為mid = low + F[K-1]-1,此時有序數組被mid划分為兩段,左段長度為F[K-1]-1,右段長度為F[k-2]-1。
若查找值大於mid值,則low等於mid+1,而k = k - 2;若查找值小於mid,則high = mid -1,k =k -1.
1 function search(array, value){ 2 let low = 0, high = array.length - 1, n = array.length - 1; 3 let mid, k = 0; 4 5 // 構建一個長度大於array數組的斐波那契數組 6 var F = []; 7 F[0]=0; 8 F[1]=1; 9 for(var i=2; i < high + 5; i++){ 10 F[i]=F[i-1]+F[i-2]; 11 } 12 13 while(high > F[k] - 1){ //尋找第k項 14 k++; 15 } 16 17 for (let i=high; i<F[k]-1; i++){ //補全有序數組 18 array[i] = array[high]; 19 } 20 21 while (low <= high){ 22 mid = low + F[k - 1] - 1; 23 if (array[mid] > value){ 24 high = mid - 1; 25 k = k - 1; //長度縮減為 F[k-1] -1 26 }else if(array[mid] < value) 27 { 28 low = mid + 1; 29 k = k - 2; //長度縮減為 F[k-2] -1 30 }else{ 31 if (mid <= n) //相等則找到位置 32 return mid; 33 else //大於原始長度,則說明等於數組最后一項 34 return n; 35 } 36 } 37 return -1; 38 }