当前位置:文档之家› 折半查找法

折半查找法

二分查找是在我们整个数据结构当中一个比较重要的算法,它的思想在我们的实际开发过程当中应用得非常广泛。

在实际应用中,有些数据序列是已经经过排序的,或者可以将数据进行排序,排序后的数据我们可以通过某种高效的查找方式来进行查找,今天要讲的就是折半查找法(二分查找),它的时间复杂度为O(logn),将以下几个方面进行概述
了解二分查找的原理与思想
分析二分查找的时间复杂度
掌握二分查找的实现方法
了解二分查找的使用条件和场景
1 二分查找的原理与思想
在上一个章节当中,我们学习了各种各样的排序的算法,接下来我们就讲解一下针对有序集合的查找的算法—二分查找(Binary Search、折半查找)算法,二分查找呢,是一种非常容易懂的查找算法,它的思想在我们的生活中随处可见,比如说:同学聚会的时候喜欢玩一个游戏——猜数字游戏,比如在1-100以内的数字,让别人来猜从,猜的过程当中会被提示是猜大了还是猜小了,直到猜中为止。

这个过程其实就是二分查找的思想的体现,这是个生活中的例子,在我们
现实开发过程当中也有很多应用到二分查找思想的场景。

比如说仙现在有10个订单,它的金额分别是6、12 、15、19、24、26、29、35、46、67 请从中找出订单金额为15的订单,利用二分查找的思想,那我们每一次都会与中间的数据进行比较来缩小我们查找的范围,下面这幅图代表了查找的过程,其中low,high代表了待查找的区间的下标范围,mid表示待查找区间中间元素的下标(如果范围区间是偶数个导致中间的数有两个就选择较小的那个)
第一次二分查找
第二次二分查找
第三次二分查找
通过这个查找过程我们可以对二分查找的思想做一个汇总:二分查找针对的是一个有序的数据集合,查找思想有点类似于分治思想。

每次都通过跟区间的中间元素对比,将待查找的区间范围缩小为原来的一半,直到找到要查找的元素,或者区间被缩小为0。

一:查找的数据有序
二:每次查找,数据的范围都在缩小,直到找到或找不到为止。

2 二分查找的时间复杂度
我们假设数据大小为n,每次查询完之后,数据就缩减为原来的一半,直到最后的数据大小被缩减为1
n,n/2,n/4,n/8,n/16,n/32,…………,1
这是一个等比数列,当数据大小变为1时,
k是总共缩小的次数,而每次缩小只涉及两个数据的比较大小,所以经过了K次区间缩小操作,通过计算k的值我们就可以得出二分查找的时间复杂度是O(logn)
这是一种非常高效的时间复杂度,有时候甚至比O(1)复杂度更高效,为什么这么说呢?因为对于logn来说即使n的非常大,对应的logn的值也会很小,之前在学习O(1)时间复杂度时我们说过O(1)代表的是一种常量级的时间复杂度,并不是说代码只需要执行一条语句,有时候可能要执行100次,1000次,这样常规级次数都用O(1)来表示,所以,常量级时间复杂度的算法有时候还没有O(logn)的算法执行效率高。

3 二分查找算法的实现
I 有序数列当中不存在重复的元素
*/
//递归二分查找//
int binaS(int*arr,int key,int high,int low) {
if(low>high)
return -1;
int mid=(high+low)/2;
if(arr[mid]==key)
{
return mid;
}
else if(arr[mid]>key)
{
binaS(arr,key,low,mid-1);
}
else
{
binaS(arr,key,mid+1,high);
}
}
int main()
{
//二分查找
int a[4]={11,22,33,44};
int key;
cin>>key;
cout<<binaS(a,key,0,3);
// int low=0,high=3,flag=1,mid;
// while(low<=high)
// {
// mid=(low+high)/2;
// if(key==a[mid])
// {
// cout<<mid<<" ";
//
// //flag=0;
// //break;
// }
// else if(key<a[mid])
// {
// high=mid-1;
II 有序数列当中存在重复的元素思路1:
//当我们的mid指针已经指向第一个元素或者我们的mid指针前一个元素不等于我们的查找
//元素的时候,直接返回mid下标
if(mid==0 || array[mid-1]!=value)
{
return mid;
} //否则,继续二分查找
else
{
high=mid-1;
}
}
else if(array[mid]<value)
{
low=mid+1;
}
else if(array[mid]>value)
{
high=mid-1;
}
}
思路2:
while(low<=high)
{
int mid=low+(high-low)/2;
if(arr[mid]==value)
{
//和查找第一个元素的思路是一样的
if(mid==len-1 || arr[mid+1]!=value) return mid;
//否则继续查找,往后查找
else
{
low=mid+1;
}
}
else if(arr[mid]>value)
{
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
if(arr[mid]>=value)
{
if(mid==0||arr[mid-1]<value) 一定要小于value 1 3 5 7 9 如果是2,那不行
return mid;
else
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
}
return -1;
*/
int binarySearch(int*arr,int value,int len)
{
int low=0,high=len-1,max=-1;
while(low<=high)
{
int mid=low+(high-low)/2;
if(arr[mid]==value)
{
if(mid==0||arr[mid-1]!=value)
{
return mid;
}
else
{
high=mid-1;
}
}
else if(arr[mid]>value)
{
max=mid;
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
}
int low=0,higg=len-1;
while(low<=high)
{
int mid=low+(high-low)>>1;
if(arr[mid]<=value) //11 22
{
if(mid==len-1||arr[mid+1]>value)
return mid;
else
low=mid+1;
}
else
{
high=mid-1;
}
}
return -1;
}
int main()
{
二分查找法的使用条件和场景
拓展:log2N → O(logN) → loga N=logcN/logca,因1/logca 不是1,所以舍去,剩下logcN,c可以是任何的值,不关心,所以是logN
案例一:跳房子(这…,看题我都要看半小时)。

相关主题