学习笔记:算法-二分查找

143 阅读2分钟

时间复杂度:运行时间的需求
空间复杂度(以存储空间换取计算时间):空间需求

顺序表查找

时间复杂度:O(n)

算法:

/* 顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字*/
int Sequential_Search(int *a,int n,int key){
    int i;
    for(i=1;i<=n;i++){      
        if(a[i]==key){
            return i;
        }
    }
    return 0;
}

优化:

/* 有哨兵顺序查找:避免查找过程中每一次比较后都要判断查找位置是否越界*/
int Sequential_Search(int *a,int n,int key){
    int i;
    a[0] = key;                /* 设置a[0]为关键字值即哨兵 */
    i = n;                     /* 循环从数组尾部开始 */
    while(a[i] != key) {
        i--;
    }
    return i;                  /* 返回0说明查找失败 */
}

有序表查找

折半查找

折半查找(二分查找):前提是关键码有序(通常是从小到大),线性表顺序存储

时间复杂度:O(logn)

算法:

int Binary_Search(int *a,int n,int key){
    int low,high,mid;
    low = 1;                         /* 定义最低下标记录首位 */
    hign = 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;              /* 若相等则说明mid即为查找的位置 */
        }
    }
    return 0;
}

备注:
计算中间值防止溢出:mid = low + (high - low) / 2
La」表示不大于a的最大整数

对于low和high之间是<= 还是<取决于target的取值范围

1. target 是在一个在左闭右闭的区间里,也就是[low, high]

  • while (low <= high),这里使用 <= ,因为low == high是有意义的,所以使用 <=
  • if (nums[middle] > target),high 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

2. target 是在一个在左闭右开的区间里,也就是[left, high)

  • while (low < high),这里使用<,因为low == high在区间[low, high)是没有意义的
  • if (nums[middle] > target),high 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以high更新为middle,即:下一个查询区间不会去比较nums[middle]

插值查找

斐波那契查找

线性索引查找

散列表查找(哈希表)

存储位置=f(关键字)