数据结构与算法练习---二分查找及其拓展代码

package searchalgroithm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BinarySearch {

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//        List<Integer> integers1 = insertSearch(arr, 7, 0, arr.length - 1);
//        System.out.println(integers1);
        int[] fibonacciArray = getFibonacciArray(20);
        System.out.println(Arrays.toString(fibonacciArray));
        int i = fiboSearch(arr, 1);
        System.out.println(i);
    }

    /**
     * 二分查找,返回与查找元素相同的元素的索引的集合
     * 只适用与有序数组
     * @param arr
     * @param findValue
     * @param left
     * @param right
     * @return
     */
    public static List<Integer> binarySearch(int[] arr, int findValue, int left, int right){
        System.out.println(333);
        if(left > right){
            return new ArrayList<>();
        }
        int mid = (left + right) / 2;
        //向左找
        if(findValue < arr[mid]){
            return binarySearch(arr , findValue , left , mid - 1);
        //向右找
        }else if(findValue > arr[mid]){
            return binarySearch(arr , findValue , mid + 1, right);
        //找到结果
        }else{
            List<Integer> resultList = new ArrayList<>();
            //向左找
            int temp = mid - 1;
            while (true){
                if(temp < 0 || arr[temp] != findValue){
                    break;
                }
                resultList.add(temp);
                temp--;
            }
            //加入原值
            resultList.add(mid);
            //向左找
            temp = mid + 1;
            while (true){
                if(temp > right || arr[temp] != findValue){
                    break;
                }
                resultList.add(temp);
                temp++;
            }
            return resultList;
        }
    }

    /**
     * 插值查找,返回与查找元素相同的元素的索引的集合
     * 只适用与有序数组,且当数组中有大量连续元素时插值查找快于二分查找
     * @param arr
     * @param findValue
     * @param left
     * @param right
     * @return
     */
    public static List<Integer> insertSearch(int[] arr, int findValue, int left, int right){
        System.out.println(222);
        if(left > right || findValue < arr[0] || findValue > arr[arr.length - 1]){
            return new ArrayList<>();
        }
        int mid = left + (right - left) * (findValue - arr[left]) / (arr[right] - arr[left]);
        //向左找
        if(findValue < arr[mid]){
            System.out.println(000);
            return insertSearch(arr , findValue , left , mid - 1);
            //向右找
        }else if(findValue > arr[mid]){
            return insertSearch(arr , findValue , mid + 1, right);
            //找到结果
        }else{
            List<Integer> resultList = new ArrayList<>();
            //向左找
            int temp = mid - 1;
            while (true){
                if(temp < 0 || arr[temp] != findValue){
                    break;
                }
                resultList.add(temp);
                temp--;
            }
            //加入原值
            resultList.add(mid);
            //向左找
            temp = mid + 1;
            while (true){
                if(temp > right || arr[temp] != findValue){
                    break;
                }
                resultList.add(temp);
                temp++;
            }
            return resultList;
        }
    }

    /**
     * 返回一个有n个元素的斐波那契数列
     * @param n
     * @return
     */
    public static int[] getFibonacciArray(int n){
        int[] arr = new int[n];
        arr[0] = 1;
        arr[1] = 1;
        for (int i = 2; i < n; i++) {
            arr[i] = arr[i - 1] + arr[i - 2];
        }
        return arr;
    }

    /**
     * 斐波那契查找,与插值查找和二分查找类似,只适用于有序数组,
     * 利用斐波那契数列的特点将分割点固定在0.618的位置
     * 非递归的方式
     * @param arr
     * @param findvalue
     * @return
     */
    public static int fiboSearch(int[] arr , int findvalue){
        int low = 0;
        int high = arr.length - 1;
        int k = 0;
        int mid = 0;
        //得到斐波那契数列
        int[] fib = getFibonacciArray(20);
        //求出k的初始值
        while(high > fib[k]){
            k++;
        }
        //创建一个新数组,并将原数组的元素拷贝至新数组中
        int[] temp = Arrays.copyOf(arr, fib[k]);
        //将新数组中比原数组中多出来的项都设置为原数组的最大值
        for (int i = high + 1; i < temp.length; i++) {
            temp[i] = arr[arr.length - 1];
        }
        //输出新数组
        //System.out.println(Arrays.toString(temp));
        //循环查找
        while (low <= high){
            //通过不断变化的low和k使mid永远维持在黄金分割点
            mid = low + fib[k - 1] - 1;
            //向左找
            if(findvalue < temp[mid]){
                high = mid - 1;
                k--;
            }else if(findvalue > temp[mid]){
                //向右找
                low = mid + 1;
                k -= 2;
            }else{
                //已找到相匹配的值
                if(mid <= high){
                    return mid;
                }else{
                    return high;
                }
            }
        }
        return -1;
    }



}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值