zoukankan      html  css  js  c++  java
  • 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 }
     
  • 相关阅读:
    解决命令行乱码问题(中文乱码)
    Outlook 修改归档文件顶层目录名
    (职员)2015-11-11 星期三 日志
    职员)2015-11-10 星期二 日志
    职员)2015-11-09 星期一 日志
    (职员)2015-11-05 星期四 日志
    (职员)2015-11-04 星期三 日志
    (职员)2015-11-03 星期二 日志
    (职员)2015-11-02 星期一 日志
    (职员)2015-10-31 星期六 周志
  • 原文地址:https://www.cnblogs.com/orxx/p/10279444.html
Copyright © 2011-2022 走看看