数据结构与算法Day06查找算法

一、二分查找

1.代码实现

思路分析:
1.编写一个方法,传入一个数组和数组第一个值位置left和最后一个值的位置right
2.让(left+right)/2就是二分的位置
3.当当前值等于需要查找的值,就返回,不等于进行判断
4.判断条件,当比mid大,向右找,进入递归,那么此时的right值不变,left变成mid+1(之前的中间值不再考虑),向左反之
5.如果此时的left>right,那么说明没有这个数据,就返回
public int search(int[] ints,int value,int left,int right){
        if(left > right){
            return -1;
        }
        int result = 0;
        int mid = (left+right)/2;
        if(ints[mid] == value){
            return mid;
        }else {
            if(ints[mid] > value){//向左找
                result = search(ints,value,left,mid - 1);
            }else {//向右找
                result = search(ints,value,mid + 1,right);
            }
        }
        return result;
    }

 2.功能完善

实现查找所有相同元素的下标

思路分析:
1.通过返回ArrayList类型返回所有元素下标
2.找到第一个元素时进行两次判断,向左找和向右找
3.当找到元素与第一个元素不同时,或者找到了数组边界,那么就结束,否则就保存索引
public ArrayList<Integer> searchPlus(int[] ints,int value,int left,int right){
        if(left > right){
            return new ArrayList<Integer>();//如果没找到,那么返回一个空的集合
        }
        int mid = (left+right)/2;
        if(ints[mid] > value){//向左找
            return searchPlus(ints,value,left,mid - 1);
        }else if(ints[mid] < value){//向右找
            return searchPlus(ints,value,mid + 1,right);
        }
        ArrayList<Integer> list = new ArrayList<>();
        int temp = mid - 1;//向左找
        while (temp >= 0){
            if(ints[temp] == value){
                list.add(temp);
                temp--;
            }else {
                break;
            }
        }

        list.add(mid);
        temp = mid + 1;//向右找

        while (temp < ints.length){
            if(ints[temp] == value){
                list.add(temp);
                temp++;
            }else {
                break;
            }
        }
        return list;
    }

二、插值查找

思路分析:
与二分查找的唯一区别就是在取mid中间值的时候使用了公式进行查找,这样更加节省了查找数据的速度
mid = left + (right - left) * (value - ints[left]) / (ints[right] - ints[left])
public static ArrayList<Integer> insertSearch(int[] ints,int value,int left,int right){
        if(left > right){
            return new ArrayList<Integer>();//如果没找到,那么返回一个空的集合
        }
        int mid = left + (right - left) * (value - ints[left]) / (ints[right] - ints[left]);
        if(ints[mid] > value){//向左找
            return insertSearch(ints,value,left,mid - 1);
        }else if(ints[mid] < value){//向右找
            return insertSearch(ints,value,mid + 1,right);
        }
        ArrayList<Integer> list = new ArrayList<>();
        int temp = mid - 1;//向左找
        while (temp >= 0){
            if(ints[temp] == value){
                list.add(temp);
                temp--;
            }else {
                break;
            }
        }
        list.add(mid);
        temp = mid + 1;//向右找
        while (temp < ints.length){
            if(ints[temp] == value){
                list.add(temp);
                temp++;
            }else {
                break;
            }
        }
        return list;
    }

插值查找注意事项

1) 对于数据量较大, 关键字分布比较均匀 的查找表来说,采用 插值查找 , 速度较快 .
2) 关键字分布不均匀的情况下,该方法不一定比折半查找要好

三、斐波那契查找(黄金分割查找)

斐波那契查找原理与前两种相似,仅仅改变了中间结点(mid)的位置,mid再是中间或插值得到,而是位于黄金分割点附近,即mid=low+F(k-1)-1F代表斐波那契数列)

F(k-1)-1的理解:

1) 由斐波那契数列 F[k]=F[k-1]+F[k-2] 的性质,可以得到  F[k]-1 = F[k-1]-1 + F[k-2]-1 +1  。该式说明:只要顺序表的长度为 F[k]-1 ,则可以将该表分成长度为 F[k-1]-1 F[k-2]-1 的两段,即如上图所示。从而中间位置为 mid= low+F (k-1)-1          
2) 类似的,每一子段也可以用相同的方式分割
3) 但顺序表长度 n 不一定刚好等于 F[k]-1 ,所以需要将原来的顺序表长度 n 增加至 F[k]-1 。这里的 k 值只要能使得 F[k]-1 恰好大于或等于 n 即可,由以下代码得到 , 顺序表长度增加后,新增的位置(从 n+1 F[k]-1 位置),都赋为 n 位置的值即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值