数据结构 插值查找 斐波那契查找

数据结构 插值查找 斐波那契查找

二分查找(折半查找):
1、它属于有序查找算法, 元素必须是有序的,如果是无序的则要先进行排序操作。
2、基本思想:
用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,
这样递归进行,直到查找到或查找结束发现表中没有这样的结点。
3、复杂度分析:
最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);

插值查找算法:
1、基于二分查找算法,属于有序查找,它将查找点的选择改进为自适应选择,从而提高查找效率
二分查找的查找点计算:
mid=(low+high)/2
插值查找的查找点:
mid=low+(key-a[low])/(a[high]-a[low])*(high-low)
它根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,间接地减少了比较次数,提高查找效率。
2、插值查找算法适合于表长较大,而关键字分布又比较均匀的查找表
3、复杂度分析:
查找成功或者失败的时间复杂度均为O(log2(log2n))

斐波那契数列(递归方法定义):
数学定义上满足F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2) (n>=2)—从第三个数开始,后边每一个数都是前两个数的和,该数列越往后相邻的两个数的比值越趋向于黄金比例值(0.618)的数列。

斐波那契查找:
它与二分查找相似(是二分查找的一种提升算法),也属于一种有序查找算法,它是根据斐波那契序列的特点对有序表进行分割的,通过在数列中选择查找点进行查找,提高查找效率。

算法思想:
在斐波那契数列找一个等于略大于查找表中元素个数的数F[k],将原查找表扩展为长度为Fk,完成后进行斐波那契分割,
即F[k]个元素分割为前半部分F[k-1]个元素,后半部分F[k-2]个元素,找出要查找的元素在那一部分并递归,直到找到该元素。

算法描述:
开始将key值与第F(k-1)位置的记录进行比较(即mid=low+F(k-1)-1),比较结果也分为三种
1、key == 查找表a[mid],mid位置的元素即为所求
2、key > 查找表a[mid],low=mid+1,k-=2;
  low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,可递归应用斐波那契查找。
3、key < 查找表a[mid],high=mid-1,k-=1。
  low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,可递归应用斐波那契查找。

复杂度分析:
最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)

public class fbsearch {
    public final static int MAXSIZE = 10;
    public static boolean runFlag = true;

    //斐波那契数列
    public static int[] fibonacci() {
        int[] f = new int[10];
        int i = 0;
        f[0] = 1;
        f[1] = 1;
        for (i = 2; i < MAXSIZE; i++) {
            f[i] = f[i - 1] + f[i - 2]; 
        }
        return f;
    }

    public static int fibonacciSearch(int[] data, int key) {

        int low = 0;
        int high = data.length - 1;
        int mid = 0;

        int k = 0;  // 斐波那契分割数值下标
        int i = 0;  
        int[] f = fibonacci(); // 构造查找所需的斐波那契数列

        // 获取斐波那契分割数值下标
        while (data.length > f[k] - 1) { 
            k++;
        }

        int[] temp = new int[f[k] - 1]; // 创建临时扩展表
        for (int j = 0; j < data.length; j++) {
            temp[j] = data[j];
        }

        // 补充表满足表长度等于f[k] - 1
        for (i = data.length; i < f[k] - 1; i++) {
            temp[i] = temp[high];  // 以原表的最后一个元素的值扩充表
        }

        if(runFlag){
            runFlag = false;
            System.out.print("斐波那契 数列:\n");
            for (int j : f) {
                System.out.print(j + " ");
            }
            System.out.println();

            System.out.println("查找表:");
            for (int j : data) {
                System.out.print(j + " ");
            }
            System.out.println();

            System.out.println("扩充后查找表:");
            for (int j : temp) {
                System.out.print(j + " ");
            }
            System.out.println();
        }

        // 表的全部元素 = 表的前半部分 + 表的后半部分
        // f[k] = f[k-1] + f[k-2]
        while (low <= high) {
            mid = low + f[k - 1] - 1; //获取表的中间点

            if (temp[mid] > key) {//查找前半部分f[k-1]
                high = mid - 1;
                k = k - 1; //更新斐波那契数列k
            } else if (temp[mid] < key) {//查找后半部分f[k-2]
                low = mid + 1;
                k = k - 2; //更新斐波那契数列k
            } else {
                // 如果为真则找到相应的位置
                if (mid <= high) {
                    return mid;
                } else {
                    // 查找到补充的元素,返回high位置的元素
                    return high;
                }
            }
        }
        return -1;
    }

    //二分查找, 非递归版本
    public static int BinarySearch1(int a[], int value, int n)
    {
        int low, high, mid;
        low = 0;
        high = n-1;
        while(low<=high)
        {
            mid = (low+high)/2;
            if(a[mid]==value)
                return mid;
            if(a[mid]>value)
                high = mid-1;
            if(a[mid]<value)
                low = mid+1;
        }
        return -1;
    }

    //二分查找,递归版本
    public static int BinarySearch2(int a[], int value, int low, int high)
    {
        int mid = low+(high-low)/2;
        if(a[mid]==value)
            return mid;
        if(a[mid]>value)
            return BinarySearch2(a, value, low, mid-1);
        if(a[mid]<value)
            return BinarySearch2(a, value, mid+1, high);
        return mid;
    }

    //插值查找
    public static int InsertionSearch(int a[], int value, int low, int high)
    {
        int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
        if(a[mid]==value)
            return mid;
        if(a[mid]>value)
            return InsertionSearch(a, value, low, mid-1);
        if(a[mid]<value)
            return InsertionSearch(a, value, mid+1, high);
        return mid;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] data = { 5, 15, 22, 25, 31, 39, 42, 45 };

        int search = 31;

        System.out.println("查找表:");
        for (int j : data) {
            System.out.print(j + " ");
        }
        System.out.println();

        int position = InsertionSearch(data, search, 0, data.length-1);
        System.out.println("插值查找:" + search + " 该元素的位置:" + position);
        System.out.println();

        position = fibonacciSearch(data, search);
        System.out.println("斐波那契查找:" + search + " 该元素的位置:" + position);

        search = 55;
        position = fibonacciSearch(data, search);
        System.out.println("斐波那契查找:" + search + " 该元素的位置:" + position);
    }
}

程序输出:

查找表:
5 15 22 25 31 39 42 45
插值查找:31 该元素的位置:4

斐波那契 数列:
1 1 2 3 5 8 13 21 34 55
查找表:
5 15 22 25 31 39 42 45
扩充后查找表:
5 15 22 25 31 39 42 45 45 45 45 45
斐波那契查找:31 该元素的位置:4
斐波那契查找:55 该元素的位置:-1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值