数据结构与算法-数组查找

2020-05-15  本文已影响0人  收纳箱

1. 顺序查找

1.1 普通顺序查找

int SequentialSearch(int *a, int n, int key) {
    for (int i = 0; i < n; i++) {
        if (a[i] == key) {
            return i;
        }
    }
    return NOT_FOUND;
}

1.2 哨兵顺序查找

我们看到,顺序查找的时候每次都要先判断i<n,能不能去掉这个判断呢?

我们可以使用一个哨兵,即数组第0位是空出来的情况,将其作为哨兵,存入查询值。

注意: 使用哨兵,①第0位存储时空出来;②返回0表示没有找到。

int SequentialSearch2(int *a, int n, int key) {
    int i = n;
    a[0] = key;
    while (a[i--] != key);
    return i;
}

2. 折半查找与变体

折半查找和相关变体,需要数组是有序的!下面的算法针对升序数组进行说明。

下面几种算法都是折半和折半公式的变式,核心都是缩小范围,利用夹逼定理进行搜索。

2.1 折半查找

通过范围折半,不断缩小搜索范围,节省时间。

int BinarySearch(int *a, int n, int key) {
    int l,c,r;
    l = 0;
    r = n-1;
    while (l <= r) {
        c = (l + r) >> 1;// 折半
        if (key < a[c]) {
            r = c - 1;
        } else if (key > a[c]) {
            l = c + 1;
        } else {
            return c;
        }
    }
    return NOT_FOUND;
}

2.2 插入查找

需要每个数据的分布是一致的。通过计算查询值在整体范围的偏移量进行查询。

int InterpolationSearch(int *a, int n, int key){
    int l,c,r;
    l = 1;
    r = n-1;
    while (l <= r) {
        //插值
        c = l + (r-l)*(key-a[l])/(a[r]-a[l]);
        if (key < a[c]) {
            r = c - 1;
        } else if (key > a[c]) {
            l = c + 1;
        } else {
            return c;
        }
    }
    return NOT_FOUND;
}

2.3 斐波那契查找

通过斐波那契数列递增的特性,反过来利用,即递减特性,缩小范围。

int F[100]; /* 斐波那契数列 */
int Fibonacci_Search(int *a, int n, int key){
    int l, c, r;
    l = 0;
    r = n-1;
    
    int k = 0;
    //1.计算n为斐波拉契数列的位置
    while (n > F[k]) {
        k++;
    }
    //2.将数组a不满的位置补全值;
    for (int i = n; i < F[k]; i++) {
        a[i] = a[n-1];
    }
    
    while (l <= r) {
        c = l + F[k-1] - 1; //计算当前分隔的下标
        if (key < a[c]) {
            r = c-1;
            k = k-1; //斐波拉契数列下标减1位
        } else if (key > a[c]) {
            l = c+1;
            k = k-2; //斐波拉契数列下标减2位
        } else {
            return c < n ? c : n-1;
        }
    }
    return NOT_FOUND;
}
上一篇 下一篇

猜你喜欢

热点阅读