在查找有序排序的时候,无意看到

1.顺序表的查找

1)顺序查找

顺序查找又称为线性查找,是一种最简单的查找方法。

        从表的一端开始,向另一端逐个按要查找的值key 与关键码key进行比较,若找到,查找成功,并给出数据元素在表中的位置;若整个表检测完,仍未找到与关键码相同的key值,则查找失败,给出失败信息。

说白了就是,从头到尾,一个一个地比,找着相同的就成功,找不到就失败。很明显的缺点就是查找效率低。

【适用性】:适用于线性表的顺序存储结构和链式存储结构。

 平均查找长度=(n+1)/2.

【顺序查找优缺点】:

缺点:是当n 很大时,平均查找长度较大,效率低;

优点:是对表中数据元素的存储没有要求。另外,对于线性链表,只能进行顺序查找。

[java]  view plain  copy
  1. public static int orederSearch(int[] array, int key) {  
  2.        if (array.length > 0) {  
  3.            for (int i = 0; i < array.length; i++) {  
  4.                if (array[i] == key) {  
  5.                    return i;  
  6.                }  
  7.            }  
  8.        }  
  9.        return -1;  
  10.    }  

2.有序表的查找

1)折半查找

 在有序表中,取中间元素作为比较对象,若给定值与中间元素的关键码key相等,则查找成功;若给定值小于中间元素的关键码,则在中间元素的左半区继续查找;若给定值大于中间元素的关键码,则在中间元素的右半区继续查找。不断重复上述查找过程,直到查找成功,或所查找的区域无数据元素,查找失败。时间复杂度为o(logn)

折半查找的前提条件是需要有序的顺序存储,对于静态查找表,一次排序后不再变化,这样的算法已经比较好。但是对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,不建议使用

[java]  view plain  copy
  1. public static int binarySearch(int[] array, int key) {  
  2.     if (array.length > 0) {  
  3.         int low, high, mid;  
  4.         low = 0;  
  5.         high = array.length - 1;  
  6.         while (low <= high) {  
  7.             mid = (low + high) / 2;//折半  
  8.             if (key < array[mid])  
  9.                 high = mid - 1;  
  10.             else if (key > array[mid])  
  11.                 low = mid + 1;  
  12.             else  
  13.                 return mid;  
  14.   
  15.         }  
  16.     }  
  17.   
  18.     return -1;  
  19. }  

2)插值查找

 插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的 查找方法,其核心就在于插值的计算公式 (key-a[low])/(a[high]-a[low])*(high-low)。时间复杂度o(logn)但对于表长较大而关键字分布比较均匀的查找表来说,效率较高

[java]  view plain  copy
  1. public static int interpolationSearch(int[] array, int key) {  
  2.        if (array.length > 0) {  
  3.            int low, high, mid;  
  4.            low = 0;  
  5.            high = array.length - 1;  
  6.            while (low <= high) {  
  7.                mid = low + (high - low) * (key - array[low]) / (array[high] - array[low]);//插值  
  8.                if (key < array[mid])  
  9.                    high = mid - 1;  
  10.                else if (key > array[mid])  
  11.                    low = mid + 1;  
  12.                else  
  13.                    return mid;  
  14.            }  
  15.        }  
  16.   
  17.        return -1;  
  18.    }  

3)斐波那契查找

      斐波那契查找的前提是待查找的查找表必须顺序存储并且有序。时间复杂度o(logn)
斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=Fk-1;
     开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种
     1)相等,mid位置的元素即为所求
     2)>   ,low=mid+1,k-=2;
     说明:low=mid+1说明待查找的元素在[mid+1,hign]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找
     3)<    ,high=mid-1,k-=1;
     说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1 个,所以可以递归 的应用斐波那契查找
     

[java]  view plain  copy
  1. public static int fbnacciSearch(int[] array, int key) {  
  2.        if (array == null || array.length == 0) {  
  3.            return -1;  
  4.        } else {  
  5.            int length=array.length;  
  6.            int[] fb=makeFbnacciArray(20);  
  7.            int k=0;  
  8.            while (length>fb[k]-1){//找出数组的长度在斐波那契数列中的位置 n<=F[k]-1  
  9.                k++;  
  10.            }  
  11.            //n不一定刚刚好等于F[k]-1 此时扩容原数组 新增的位置的值为原数组的最大值  
  12.            int[] temp= Arrays.copyOf(array,fb[k]-1);  
  13.            for (int i=length;i<temp.length;i++){  
  14.                if(i>=length){  
  15.                    temp[i]=array[length-1];  
  16.                }  
  17.            }  
  18.            int low=0;  
  19.            int high=array.length-1;  
  20.            while (low<=high){  
  21.                int middle=low+fb[k-1]-1;  
  22.                if(temp[middle]>key){  
  23.                    high=middle-1;  
  24.                    k=k-1;  
  25.                }else if(temp[middle]<key){  
  26.                    low=middle+1;  
  27.                    k=k-2;  
  28.                }else{  
  29.                    if(middle<=high){  
  30.                        return  middle;//若相等则说明middle为查找的位置  
  31.                    }else{  
  32.                        return high;//middle的值已经大于high,进入扩展数组的填充部分,既最后一个数就是要查找的数  
  33.                    }  
  34.                }  
  35.            }  
  36.        }  
  37.   
  38.        return -1;  
  39.    }  
  40.   
  41.    private static int[] makeFbnacciArray(int length) {  
  42.        int array[] = null;  
  43.        if (length > 2) {  
  44.            array = new int[length];  
  45.            array[0] = 1;  
  46.            array[1] = 1;  
  47.            for (int i = 2; i < length; i++) {  
  48.                array[i] = array[i - 1] + array[i - 2];  
  49.            }  
  50.        }  
  51.        if (length == 2) {  
  52.            array = new int[length];  
  53.            array[0] = 1;  
  54.        }  
  55.        if (length == 1) {  
  56.            array = new int[length];  
  57.            array[0] = 1;  
  58.            array[1] = 1;  
  59.        }  
  60.        return array;  
  61.    }  

4.总结

三种有序表的查找本质是分割点的选择不同,各有优劣,实际开发时可根据数据的特点综合考虑再做选择。这里注意主要的运算,折半查找采用乘除(mid = (low + high) / 2 )、插值采用的是四则运算(  mid = low + (high - low) * (key - array[low]) / (array[high] - array[low])),斐波那契采用的是加减(middle=low+fb[k-1]-1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值