二分搜索算法
来源:互联网 发布:淘宝上的头层牛皮沙发 编辑:程序博客网 时间:2024/04/30 06:20
1. 算法思想:分治,从表中间开始查找目标元素。如果找到一致元素,则查找成功。如果中间元素比目标元素小,则仍用二分查找方法查找表的后半部分(表是递增排列的),反之中间元素比目标元素大,则查找表的前半部分。
2. 前提条件:
1) 查找表必须为有序状态(递增排列或递减排列),本文使用的表中数据是递增的。
2) 查找表为数组形式(内存连续)的数据结构;如果是链表(内存不连续)的数据结构二分查找无法使用,即便采用二分查找的思想也达不到时间复杂度O(logN),因为无法直接定位中间元素(O(1))。
3. 优缺点:
1) 优点是比较次数少,查找速度快,平均性能好;
2) 缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
4. 二分搜索的三种实现:
1) 版本一:查找范围为[lowbound, highbound):左闭右开
int binarysearch(int targetarray[],intlowbound,int highbound,int targetvalue){ int mid; while(lowbound<highbound)//注意此处是严格的<号 { mid=lowbound+(highbound-lowbound)/2;//这样可以避免数据的溢出 if(targetarray[mid]==targetvalue) { return mid; } if(targetarray[mid]>targetvalue) { highbound=mid;//注意此处没有-1 } else { lowbound=mid+1; } } return -1;//找不到返回-1}
2) 版本二: 查找范围为[lowbound, highbound]
int binarysearch(int targetarray[],intlowbound,int highbound,int targetvalue){ int mid; while(lowbound<=highbound)//注意此处是<=号 { mid=lowbound+(highbound-lowbound)/2;//这样可以避免数据的溢出 if(targetarray[mid]==targetvalue) { return mid; } if(targetarray[mid]>targetvalue) { highbound=mid-1;//注意此处有-1 } else { lowbound=mid+1; } } return -1;//找不到返回-1}
3) 递归版本的版本2:
int recursivebinarysearch(int a[10],intlow,int high,int target){ if(low>high) { return -1;} int mid=low+(high-low)/2; if(a[mid]==target) { return mid;} if(a[mid]<target) { return recursivebinarysearch(a,mid+1,high,target);//分治 } return recursivebinarysearch(a,low,mid-1,target);}
5. 时间复杂度为:O(logN)。空间复杂度为:O(1)
时间复杂度分析:以版本2为例。在while循环内部的所有语句用时O(1),所以主要分析循环次数。初始状态highbound-lowbound假设为N,每次这个差值至少减少一半,直至lowbound=highbound+1,所以大约最多执行logN次循环。所以时间复杂度为O(logN)。
6. 测试程序:
#include<iostream>usingnamespace std; inta[10]= {0,1,2,3,4,5,6,7,8,9}; intbinarysearch1(int a[10],int low,int high,int target);int binarysearch2(inta[10],int low,int high,int target);intrecursivebinarysearch(int a[10],int low,int high,int target); intmain(){ cout<<"使用第一种查找函数,查找数字8,上下限分别为3,8;查找结果为:"; int result=binarysearch1(a,3,8,8); if(result!=-1) { cout<<"已找到,下标为:"<<result<<endl; } else { cout<<"没有找到"<<endl; } cout<<"使用第二种查找函数,查找数字8,上下限分别为3,8;查找结果为:"; int result2=binarysearch2(a,3,8,8); if(result2!=-1) { cout<<"已找到,下标为:"<<result2<<endl; } else { cout<<"没有找到"<<endl; } cout<<"使用第三种查找函数,查找数字8,上下限分别为3,8;查找结果为:"; int result3=recursivebinarysearch(a,3,8,8); if(result3!=-1) { cout<<"已找到,下标为:"<<result2<<endl; } else { cout<<"没有找到"<<endl; } return 0;} intbinarysearch1(int a[10],int low,int high,int target){ while(low<high) { int m=low+(high-low)/2; if(a[m]==target) { return m; } if(a[m]>target) { high=m; } else { low=m+1; } } return -1;} intbinarysearch2(int a[10],int low,int high,int target){ while(low<=high) { int m=low+(high-low)/2; if(a[m]==target) { return m; } if(a[m]>target) { high=m-1; } else { low=m+1; } } return -1;} intrecursivebinarysearch(int a[10],int low,int high,int target){ if(low>high) { return -1; } int mid=low+(high-low)/2; if(a[mid]==target) { return mid; } if(a[mid]<target) { returnrecursivebinarysearch(a,mid+1,high,target); } returnrecursivebinarysearch(a,low,mid-1,target);}
运行结果为:
使用第一种查找函数,查找数字8,上下限分别为3,8;查找结果为:没有找到
使用第二种查找函数,查找数字8,上下限分别为3,8;查找结果为:已找到,下标为:8
使用第三种查找函数,查找数字8,上下限分别为3,8;查找结果为:已找到,下标为:8
解析:版本一的二分查找查找的区间是:[lowbound,highbound),左闭右开:首先我们要知道对于一对整数求它们的平均值(int类型),平均值要么正好在中间,要么偏向小的一方,永远不可能偏向大的一方,该版本的while循环的退出条件是lowbound==highbound,因此highbound对应的数组元素永远不会被比较,因此如上例程序,第一种没有找到数字8;版本二的二分查找查找的区间是:[lowbound,highbound],左闭右闭,该版本的while循环的退出条件是lowbound==highbound+1,因此highbound对应的数组元素会被比较,因此如上例程序,第二种找到数字8。版本三的道理同版本二。
- 【基础算法】搜索-二分搜索
- C#二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 简单算法--二分搜索
- 二分搜索算法细节
- 研究二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 二分搜索算法
- 分治算法--二分搜索
- java二分搜索算法
- ubuntu中安装mysql和mysql-workbench
- VS2013启动越来越慢
- sql
- 黑马程序员_强大的IO流
- 微信自媒体运营之取消关注公众号跟踪
- 二分搜索算法
- cocos2d-x 2.2.3 CCKeypadDispatcher简单分析
- PHP学习日记-上传文件
- “市场导向”需要新的文化观
- 数据库第四次实验内容
- 安卓图表------为github开源控件MPAndroidChart 添加横参考线
- 数制转换
- ssh 出现key_read 问题
- 冒泡法排序