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

来源:互联网 发布:不能说的夏天 知乎 编辑:程序博客网 时间:2024/06/09 21:19

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

二分查找(折半查找):
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 0
原创粉丝点击