折半查找
折半查找算法也叫二分查找
该算法重点是有序!有序!有序!
二分查找的时间复杂度为
在一个有序数组中查找具体的某个数字n。
例:
假如买一双鞋,着一双鞋在1~100之间的价格
我让你猜这双鞋多少钱?你不会一块,两块三块四块......这么猜
一般情况下会从50?小了。75?大了.62?
这样猜出价格的效率会高很多
折半查找方法
1.确定查找区间 [ left, right]
2.每次查找范围缩小一半
计算中间位置,用想要查找的值与arr[mid]的值作比较,有三种可能
注:这里的mid是中间值的下标 , 不是中间值 arr[mid]才是是中间值
(1)如果arr[mid]比查找的值大,更新right = mid - 1;
(2)如果arr[mid]比查找的值小,更新left = mid + 1;
(3)如果相等,则查找成功
3。结束条件只有在查找成功跳出,或者是left > right跳出(查找失败)
完整代码
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//假设有10个数字
//查找的数字为7
int k = 7;
//求元素个数
int sz = sizeof(arr) / sizeof(arr[0]);
//左边从0开始,左下标
int left = 0;
//数组下标从0开始,右下标
int right = sz - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else if (arr[mid] == k)
{
printf("查找的数字找到了,下标为%d", mid);
break;
}
}
if (left > right)
{
printf("该数字不存在");
}
return 0;
}
下标优化
该代码有一个可以优化的地方
如果left和right加起来是一个很大的数字,超过了整数的最大值,再除以2就不是我们想要的值 我们要怎么改呢?
int mid = left + (right - left)/2;//中间元素下标
这样就不会越界,right不能越界,自然left也就不能越界
二叉判定树
折半查找的过程还可以使用二叉树来描述,例如,可以借助于下面的二叉树来说明刚才折半查找的过程
二叉判定树例题
判定树的构成:从查找区间开始,根节点对应查找区间的终点记录,它的左子树对应左子区间,它的右子树对应右子区间
例如:查找的目标为33,33大于29,走29(根结点)的右子树,此时根节点变为37,33小于37,走37(根节点)的左子树,此时根节点变为32,33大于32,走32的右子树,找到33
通过看图可以看出,
判定树的层次就是二分查找的次数
不论查找的成功与否折半查找过程所需要的比较次数不查过判定树的高度
个人水平不足 如果代码中有错误,可以多多在评论区指出,一定会及时修改!
谢谢大家看到这里 觉得有收获的话可以三连一下 一起加油!