有序表查找

1 概念
  查找表(Search Table)是由同一类型的数据元素(或记录)构成的集合。
  查找就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
  查找表按照操作方式可以分为两大种:静态查找表和动态查找表。
  (1)静态查找表:只做查找操作的查找表。
  (2)动态查找表:在查找的过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。

2 有序表查找

(1)折半查找(二分查找)
  折半查找的前提是线性表中的记录必须是关键码有序(通常从小到大排序),线性表必须采用顺序存储。

//折半查找
int Binary_Search(int *a, int n, int key) {
    int low, high, mid;
    low = 1;                    //定义最低下标的记录首位
    high = n;                    //定义最高下标的记录末位
    while(low <= high) {
        mid = (low + high)/2;
        if (key < a[mid]) {
            high = mid - 1;
        } else if (key > a[mid]) {
            low = mid + 1;
        } else {
            return mid;
        }
    }
    return 0;
}

(2) 插值查找
    折半查找的mid = (low + high)/2 = low + (high - low) * (1/2),也就是mid等于最低下标low加上最高下标high与最低下标low的差的一半。算法科学家将(1/2)改进为(key - a[low])/ (a[high] - a[low]).
    对于表长较大,而关键字分布比较均匀的查找表来说,插值查找的性能比折半查找的性能要高很多。反之,若查找表中的数据{1,2,3,200,300, ..., 8000,9000}分布极度不均匀,则
插值查找未必是很好的选择。

(3) 斐波那契查找

//斐波那契查找
int Fibonacci_Search(int *a, int n, int key) {
    int low, high, mid, i, k;
    low = 1;
    high = n;
    k = 0;
    while (n > F[k] - 1) {                    //计算n位于斐波那契数列的位置
        k ++;    
    }
    for (i = n; i < F[k] - 1; i ++) {        //将不满的数值补全
        a[i] = a[n];
    }
    while (low <= high) {
        mid = low + F[k - 1] - 1;            //计算当前分割的下标
        if (key < a[mid]) {
            high = mid - 1;                    //最高下标调整到分割下标mid-1处
            k = k - 1;                        //斐波那契数列下标减1
        } else if (key > a[mid]) {
            low = mid + 1;                    //最低下标调整到分割下标mid+1处
            k = k - 2;                        //斐波那契数列下标减2
        } else {
            if (mid <= n) {
                return mid;                    //若相等则说明mid即为查找到的位置
            } else {
                return n;                    //若mid > n, 说明是补全数值,返回n
            }
        }
    }
    return 0;
}

3 三种查找方法比较
    折半查找是进行加法和除法运算 mid = low + (high - low)/2, 插值查找是进行复杂的四则运算 mid = low + (high - low) * (key - a[low])/(a[high] - a[low]), 而斐波那契查找只是最简单的加减法运算 mid = low + F[k - 1] - 1, 在海量数据的查找过程中,这种细微的差别可能会影响最终的查找效率。
    三种查找的本质区别是分隔点的选择不同,各有优劣,实际开发中可根据数据的特点综合考虑后再做决定。

原文地址:https://www.cnblogs.com/muzijie/p/5715991.html