2.2 二分法查找(又叫分半查找、拆半查找)
//二分法的代码必须会写
//林青霞 ----> 东方不败 ---> 《葵花宝典》---> 《葵花宝典》第一页
二分法查找 使用是有前提条件的
前提条件:数组必须是一个有序的序列 可以是递增的 也可以是递减的
思想:要查找的数据x,每次与中间的位置的元素进行比较大小,来判断
被查找的数据x,可能在 中间的左半部分 还是 右半部分
#include <stdio.h>
int findByHalf(int* p, int n, int x)
{
int low = 0;//数组的起始下标
int high = n-1;//数组的终止下标
int middle;//用来保存中间位置的下标
while(low <= high)//注意此处,low==high,循环继续运行 low > high循环结束
{
//1.得到中间位置的下标
middle = (low+high) / 2;
//2.将x与中间位置的元素做比较
if(x == p[middle])
return middle;
else if(x > p[middle])//假设是递增的数组,说明x可能在中间位置的右侧,所以移动low
low = middle + 1;
else if(x < p[middle])//假设是递增的数组,说明x可能在中间位置的左侧,所以移动high
high = middle - 1;
}
//如果while循环结束后,都没有执行return middle,说明没有找到
return -1;//用-1来代表没有找到
}
int main(int argc, const char *argv[])
{
int a[8] = {1,3,5,7,9,10,12,15};
//写个循环,将数组中的所有元素都用二分法查找一次
int i;
for(i = 0; i < 8; i++)
{
int ret = findByHalf(a,8,a[i]);
if(ret == -1)
printf("not find!!\n");
else
printf("%d的下标是%d\n",a[ret],ret);
}
return 0;
}
//二分法的时间复杂度 T(n) = O(log(n)) //log以2为底,n的对数
问题规模 N
查找数据长度为N,每次查找后减半,
第一次 N/2
...
第k次 N/2^k
最坏的情况下第k次才找到,此时只剩一个数据,长度为1。
即 N/2^k = 1
查找次数 k=log(N)。
// 第一次 N / 2
// 第二次 N / 2 / 2 == N / 2^2
// 第三次 N / 2 / 2 / 2 == N / 2^3
// 第k次 N / 2^k //第k次查找,也就意味着循环了k次,循环的次数k和问题规模的关系
//分了多少次半,也就是查找了多少次,也就是循环了多少次
N / 2^k = 1
2^k = N;
k = log2 N //以2为底,N的对数 ---> log(N) //以2为底的2 ,省略不写
T(n) = O(log(n))
二分查找 重点: 代码编写 + 时间复杂度 log(n) //以2为底n的对数