JS-7种查找算法之顺序查找、二分查找、插值查找、斐波那契查找

参考链接 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 }

 

 
posted @ 2019-01-16 21:15  orxx  阅读(1490)  评论(0编辑  收藏  举报