算法概述#
二分查找(英语:binary search),也叫折半查找(英语:half-interval search),是一种在有序数组中查找特定元素的搜索算法。所以,二分查找的前提是数组必须是有序的。
时间复杂度、空间复杂度请参照下图(图片来自wikipedia):

适用情况#
二分查找只适用顺序存储结构。为保持表的有vb.net教程序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。

对那些查找少而又经常需要改动的线性表,可采用c#教程链表作存储结构,进行顺序查找。链表上无法实现二分查找(更准确的说链表上使用二分查找得不偿失)。

算法原理#
二分查找的基本思想是:

设R[low……high]是当前的查找区间。
首先确定该区间的中点位置:mid = low + ((high - low) >> 1)。
然后将待查的target值与ary[mid]比较:若相等,则查找成功并返回此位置,否则须确定新的查找区间,继续二分查找。
若ary[mid]>target,则由表的有序性可知ary[mid….high]均大于K,因此若表中存在关键字等于target的结点,则该结点必定是在位置mid左边的子表R[low…mid-1]中,故新的查找区间是左子表ary[low……mid-1]。
若ary[mid]<target,则要查找的target必在mid的右子表ary[mid+1……high]中,即新的查找区间是右子表ary[mid+1……high]。
下一次查找是针对新的查找区间进行的。
因此,从初始的查找区间R[0…n-1]开始,每经过一次与当前查找区间的中点位置上的结点关键字的比较,就可确定查找是否成功,不成功则当前的查找区间就缩小一半。这一过程重复直至找到关键字为target的结点,或者直至当前的查找区间为空(high<low,即查找失败)时为止。

算法实现(C#)#
算法基于C#编写,有简单和泛型两种实现,每种实现又分递归版本、While循环版本。实际运用时,推荐使用While循环版本的二分查找。
算法代码如下:

//此算法假定数组已排序;如果不是这样,则结果将不正确。
class BinarySearch
{//不要使用mid = (high + low) / 2,可能会导致运算溢出#region 简单// 递归版本           public static int Recursive(int[] ary, int target){return Recursive(ary, 0, ary.Length-1, target);           }static int Recursive(int[] ary, int low, int high, int target){if (high < low) return -1;    int mid = low + ((high - low) >> 1);if (ary[mid] == target) return mid;if (ary[mid] > target){return Recursive(ary, low, mid-1, target);}else{return Recursive(ary, mid + 1, high, target);}            }//While循环版本public static int WhileLoop(int[] ary, int target){int low = 0; int high = ary.Length - 1;while (low <= high){                                int mid = low + ((high - low) >> 1);if (ary[mid] == target) return mid;if (ary[mid] > target){high = mid - 1;}else {low = mid + 1;}}return -1;}#endregion#region 泛型// 递归版本           public static int RecursiveT<T>(T[] ary, T target) where T : IComparable{return RecursiveT(ary, 0, ary.Length - 1, target);}static int RecursiveT<T>(T[] ary, int low, int high, T target) where T : IComparable{               if (high < low) return -1;            int mid = low + ((high - low) >> 1);int cr = Comparer.Default.Compare(ary[mid], target);             if(cr==0)return mid;if (cr > 0){return RecursiveT(ary, low, mid - 1, target);}else {return RecursiveT(ary, mid + 1, high, target);}            }//While循环版本public static int WhileLoopT<T>(T[] ary, T target) where T : IComparable{int low = 0;int high = ary.Length - 1;while (low <= high){                int mid = low + ((high - low) >> 1);int cr = Comparer.Default.Compare(ary[mid], target);                if (cr == 0) return mid;if (cr>0){high = mid - 1;}else {low = mid + 1;}               }return -1;}//默认情况下推荐使用While循环版本public static int DefaultT<T>(T[] ary, T target) where T : IComparable {            return WhileLoopT(ary, target);}#endregion
}

测试代码如下:

//数组必须有序
//此处用升序递增的整数数组是为了便于检查结果
int[] ary = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
long[] aryT = new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
int target = 8;
int r = BinarySearch.Recursive(ary, target);
int w = BinarySearch.WhileLoop(ary, target);
int rT = BinarySearch.RecursiveT(ary, target);
int wT = BinarySearch.WhileLoopT(ary, target);
Console.WriteLine("r={0} w={1} rT={2} wT={3}", r, w, rT, wT);

实际应用:用二分查找法找寻边界值#
在集合中找到一个大于(小于)目标数t的数x,使得集合中的任意数要么大于(小于)等于x,要么小于(大于)等于t。
举例来说:给予数组和目标数

int array = {2, 3, 5, 7, 11, 13, 17};
int target = 7;
那么上界值应该是11,因为它“刚刚好”大于7;下界值则是5,因为它“刚刚好”小于7。

该问题不能直接使用二分查找的实现代码解决,需要对代码做一些修改,但解题思路还是二分查找。

实现代码如下:

//用二分查找法找寻上界
static int BSearchUpperBound(int[] ary, int target)
{           int low = 0;int high = ary.Length - 1;            while (low <= high){int mid = low + ((high - low) >> 1);if (high == low) {if (ary[mid] > target) return mid;else return -1;            }if (ary[mid] > target){//当前找到的数大于目标数时,它可能就是我们要找的数,所以需要保留这个索引high = mid ;}else{//当前找到的数小于等于目标数时继续向上取区间low = mid + 1;}}return -1;
}//用二分查找法找寻下界
static  int BSearchLowerBound(int[] ary, int target)
{int low = 0;int high = ary.Length - 1;while (low <= high){//取中间索引时使用向上取整,否则low无法往上爬到下界值int mid = low + ((high - low + 1) >> 1);if (high == low){if (ary[mid] < target) return mid;else return -1;}               if (ary[mid] >= target){//当前找到的数大于等于目标数时继续向下取区间high = mid-1;}else{//当前找到的数小于目标数时,它可能就是我们要找的数,所以需要保留这个索引low = mid;}}return -1;
}

测试代码如下:

//寻找边界值
int[] array =new int[]{ 2, 3, 5, 7, 11, 13, 17 };
int target =6;
//用二分查找法找寻上届
int up = BSearchUpperBound(array, target);
int lo=BSearchLowerBound(array, target);
参考文章#
二分搜索(Binary_Search)——简书
binary search——百度百科
BinarySearch——.NET源码
二分查找BinarySearch原理分析、判定树、及其变种——CSDN
二分查找法的实现和应用汇总——CSDN

作者: time-flies

出处:https://www.cnblogs.com/timefiles/p/BinarySearch.html

简单实用算法——二分查找法(BinarySearch)相关推荐

  1. java 二分查找_计算机入门必备算法——二分查找法

    1.引言 笔者对于计算机的研究一直停滞不前,近期想对一些算法进行复习和进一步的研究,每天都会更新一个新的算法,算法有难有易,层层递进.不希望能学的有多么高深,只希望在一些最基本的算法上有编码的思路,或 ...

  2. binarysearch java,java数据结构之二分查找法 binarySearch的实例

    java数据结构之二分查找法 binarySearch的实例 折半查找法,前提是已经排好序的数组才可查找 实例代码: public class BinarySearch { int[] bArr; p ...

  3. Java-数据结构与算法-二分查找法

    1.二分查找法思路:不断缩小范围,直到low <= high 2.代码: 1 package Test; 2 3 import java.util.Arrays; 4 5 public clas ...

  4. NTC测温中 经典温度查表算法--二分查找法

    说明: 二分查找法的优点:查找速度快 1024个长度的表最长只需10次查表就能得出结果 在用NTC测试温度的方案中,NTC的温度表的长度一般是100-200 有些达到400-500的长度 在这种情况下 ...

  5. 折半查找算法[二分查找法]算法的实现和解决整数溢出问题~

    算法实现的要求: 折半查找法又称为二分查找法,这种方法对待查找的列表有两个要求: 1:必须采用顺序存储结构 2:必须按关键字大小有序排列 算法思想: 将表中间位置记录的关键字与查找关键字进行比较,如果 ...

  6. 每日一则----算法----二分查找法

    php实现二分查找法 二分查找法称折半查找,需要数组是一个有序的数组 假设我们的数组是一个递增的数组,首先我们需要找到数组的中间位置. 要知道中间位置就需要知道起始位置和结束位置,然后取出中间位置的值 ...

  7. java二分查找法_java算法之二分查找法的实例详解

    java算法之二分查找法的实例详解 原理 假定查找范围为一个有序数组(如升序排列),要从中查找某一元素,如果该元素在此数组中,则返回其索引,否则返回-1.通过数组长度可取出中间位置元素的索引,将其值与 ...

  8. Python 关于下标的运用技巧(二分查找法,冒泡、选择、插入、归并、快速排序算法)

    二分查找法(折半查找法)的递归实现 二分查找法(折半查找法):用于预排序列表的查找问题, 再次强调,二分查找法要配合排序使用,只有排好序,才能使用二分查找法 而且,待查找列表如果有重复值,只能查找到其 ...

  9. java算法2_二分查找法

    比如现在有个记录名单的字典,里面的名字是按A-Z的顺序排好的,现在我想找Lily这个人.我可以从第一页开始一页一页的翻,但显然这样效率太低了.我可以怎么做呢?首先我直接翻到字典的中间位置,假如发现这里 ...

  10. 小白的算法初识课堂(part1)--二分查找法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 二分查找法 算法是一组完成任务的指令,任何代码片段都可视为算法.二分查找是一种算法,其输入是一个有序的元素列表(必须有序 ...

最新文章

  1. python模块之re正则表达式
  2. 2020 JVM生态报告
  3. 企业要搞数字化转型,是用一整套ERP,还是各搞各的数据系统?
  4. DBA生存警示:防范频发的数据误删除操作
  5. ubuntu 国内源
  6. 分享我的Windows live writer 使用经验
  7. NUMA全称 Non-Uniform Memory Access,译为“非一致性内存访问”,积极NUMA内存策略
  8. dw二级联动下拉菜单插件 宋君墨_Excel下拉菜单不会做?15秒教会你制作一二三级联动下拉菜单,从此做表不求人!...
  9. 一个针对.net的好的建模工具 powerdesign 11
  10. C#中如何调用动态链接库DLL
  11. 如何配置filezilla服务端和客户端
  12. dnslog盲打学习
  13. 2020第三届中青杯问题总结
  14. Codeforces Round #306 (Div. 2)
  15. 计算机网络:数据链路层
  16. 三轮全向底盘:运动学性能分析
  17. 从普通温度表到高精度测量
  18. 集线器,交换机与路由器
  19. CSS3 animation-fill-mode 属性
  20. 看雪2w3w安卓高级研修Frida原理学习

热门文章

  1. vivo双卡流量切换流程
  2. 有没有一款桌面便签软件,可以手机电脑都能使用的?
  3. 带sex的net域名_域名劫持的几种方法、域名劫持有什么方式
  4. 各类分布以及检验方法
  5. java代码从初始化到具象执行
  6. java开源im框架_开源im即时通讯
  7. 老男孩教育Linux50期远程控制连接
  8. chrome浏览器无法安装crx插件的解决方法(以翻译插件为例)
  9. Chrome 翻译插件规避代码块
  10. Folium库使用心得(二)