二分查找法
来源:互联网 发布:java类变量初始化 编辑:程序博客网 时间:2024/06/07 06:19
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,占用系统内存较少。
其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
对于二分查找法,首先我们获取需要查找的数组的左边界l和右边界r,然后在通过左右边界计算出数组中中间的位置mid,但是计算mid不能简单的使用mid=(l+r)/2去计算,因为当l和r都接近于int的最大值时,我们求l+r就会发生int变量越界的情况,因此我们这样去求mid的值:mid=l+(l+r)/2(左边界加上一半的偏移量)。
具体如下图所示:
也可以运用递归的思想去实现二叉搜索,先判断我们要查找的target与mid处值的大小,如果运气非常好,target=arr[mid]的话,则直接return target就好了,如果小于mid,则把搜索的边界缩小,使其右边界为mid-1,相反,如果大于mid,则使其左边界变为mid+1,总之,就是在不断的缩小数组的查找范围,每一次查找都能排除上一步一半的数据,因此,二叉搜索是一种非常高效的搜索方法,以下是具体的代码:
#include <iostream>#include <cassert>#include <ctime>using namespace std;/**二分查找法,在有序数组中查找目标target * 返回目标target在数组中相对应的索引 * 如果数组中不存在目标target,则返回-1*/template <typename T>int binarysearch(T arr[],int n,T target)//n为数组的总数,target为要查询的目标{ //在[l,r]中搜索target int l,r,mid;//l为搜索的左边界,r为搜索的右边界,mid为中间的元素 l=0,r=n-1; while(l<=r){//注意此时l可以等于r mid=l+(r-l)/2;//不采用(l+r)/2的算法求mid是为了防止Int变量越界 if(arr[mid]==target) return mid; else if(target<arr[mid]){ r=mid-1; } else{ l=mid+1; } } return -1;}template <typename T>int __binarysearch(T arr[],int l,int r,T target){//对数组中的[l,r]进行操作,l为起始搜索位置,r为终止搜索位置,mid为中间位置 if(l>r) return -1; int mid; mid=l+(r-l)/2;//不采用(l+r)/2的算法求mid是为了防止Int变量越界 if(target==arr[mid]) return mid; else if(target<arr[mid]) __binarysearch(arr,l,mid-1,target); else __binarysearch(arr,mid+1,r,target);}template <typename T>int binarysearch2(T arr[],int n,T target){ return __binarysearch(arr,0,n-1,target);}//生成测试案例为一个大小为1000000的数组,查询超出1000000的则返回-1int main() { //生成测试案例为一个大小为1000000的数组,查询超出1000000的则返回-1 int n=1000000; int *a=new int[n]; for(int i=0;i<n;i++) { a[i]=i; }//测试非递归算法clock_t starttime=clock(); for(int i=0;i<2*n;i++) { int ret=binarysearch(a,n,i); if( i < n ) assert( ret== i ); else assert( ret== -1 ); } clock_t endtime=clock(); cout<<"Binary Search (Without Recursion):"<<double(endtime-starttime)/CLOCKS_PER_SEC<<'s'<<endl; //测试递归的二叉搜索法 starttime=clock(); for(int i=0;i<2*n;i++) { int ret=binarysearch2(a,n,i); if(i<n) assert(ret==i); else assert(ret==-1); } endtime=clock(); cout<<"Binary Search (Recursion):"<<double(endtime-starttime)/CLOCKS_PER_SEC<<"s"<<endl; delete[]a; return 0;}
接下来我们看一下测试的结果:
我们发现,使用递归算法较好的描述了二分查找法,但是性能上却会略有下降。
阅读全文
0 0
- 查找----二分查找法
- 二分查找法,查找string
- 二分查找法
- 二分查找法
- 二分查找法
- 二分查找法
- java 二分查找法
- 二分查找法
- 二分查找法
- 二分查找法
- 二分查找法
- java:二分查找法
- C++ 二分查找法
- 二分查找法
- 【二分查找法】
- php二分查找法
- 二分查找法
- 二分查找法
- Java 开发环境配置
- SVN和Git的区别
- Java 基本数据类型
- Collections.synchronizedMap()、ConcurrentHashMap、Hashtable之间的区别 为什么要比较Hashtable、SynchronizedMap()、Co
- 做小程序费用太高?帮你选一个最省钱的方案
- 二分查找法
- 论文笔记:Personalized Tag Recommendation for Images Using Deep Transfer Learning
- 微服务MySQL分库分表数据到MongoDB同步方案
- windows+R 运行 快捷命令
- php获取leancloud的多重数组
- 【体感手势】口袋模式或者防误触
- IDEA入门级使用教程
- 应该使用FOUNDATION_EXPORT还是#define来定义常量?
- 如何在CSDN中添加好友