之前写过一篇极为罗嗦的二分查找,非常得意地以为以后就可以避免踩坑了,但是今天才知道二分查找可以写的既简洁又鲁棒,唉!还是要多学习啊!

给一个按照从大到小的顺序排序好的数组a[]={1,2,3,4,7,7,7,8,9,10};

用二分查找分别求等于4,大于7的第一个数,大于等于7的第一个数,小于7的最大的数,小于等于7的最大的数。

如果写的不小心的话非常容易陷入死循环,有的时候写二分可能也会面临是l = mid还是l=mid+1这样的纠结,所以本文要证明,这几种查询的方式是可以

统一在一起的,只需要重载元素的小于号,就可以完成所有的工作

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n;
  4. int a[] = {,,,,,,,,,};//以升序列为例,降序也一样道理
  5.  
  6. bool cmp(int x,int v)
  7. {
  8. return x < v;//判断a[mid]和所要查找的边界值的关系,
    //我们只需要一个小于号就可以表示出大于,等于,小于,大于等于,小于等于,这也是为什么在sort里面需要重载小于号即可。
  9. }
  10.  
  11. int b_search(int a[],int n,int v)//精确查找数组里是不是有等于v的元素
  12. {
  13. int l = -,r = n;//把l,r预先设定成两个边界值,在查找大于小于的时候非常有用,下面再说。
  14. for(int mid;r-l>;){//强烈建议多用for,少用while
  15. mid = (l+r)>>;
  16. if(!cmp(a[mid],v)&&!cmp(v,a[mid])) return mid;//如果a【mid】不小于v,反之也不成立,只能是相等了,直接返回地址
  17. else if(cmp(a[mid],v)) l = mid+;//a【mid】小于v此时a[mid]在v的右边,所以查找区间应该右移
  18. else r = mid-;//反之同理
  19. }
  20. if(a[l] == v) return l;//如果最后得到的地址的值确实等于要查找的值,返回地址。
  21. else return -;//否则,返回-1
  22. }
  23.  
  24. int upperequal(int a[],int n,int v)//大于等于v的最小的数,相当于stl的lower_bound函数
  25. {
  26. int l = -,r = n;//这里有一个隐含的意思是l是小于v的,r是大于v的那个元素,一直保持这样就可以不陷入死循环
  27. for(int mid;r-l>;){
  28. mid = (l+r)>>;
  29. if(!cmp(a[mid],v)) r = mid;//注意这里判断的是a【mid】是不是大于等于v,
  30. else l = mid;
  31. }
  32. return r;//因为r在变化过程中一直是大于等于v的,所以r就是答案
  33. }
  34. int upper(int a[],int n, int v)//二分查找大于v的第一个数,相当于stl里面的upperbound
  35. {
  36. int l = -,r = n;
  37. for(int mid; r-l>;){
  38. mid = (l+r)>>;
  39. if(cmp(v,a[mid])) r = mid;
  40. else l = mid;
  41. }
  42. return r;
  43. }
  44. int lower(int a[],int n, int v)//查找小于v的最大的元素
  45. {
  46. int l = -,r = n;
  47. for(int mid; r-l>;){
  48. mid = (l+r)>>;
  49. if(cmp(a[mid],v)) l = mid;
  50. else r = mid;
  51. }
  52. return l;
  53. }
  54. int lowerequal(int a[],int n, int v)查找小于等于v的最大的元素
  55. {
  56. int l = -,r = n;
  57. for(int mid;r-l>;){
  58. mid=(l+r)>>;
  59. if(!cmp(v,a[mid])) l = mid;
  60. else r = mid;
  61. }
  62. return l;
  63. }
  64. int main()
  65. {
  66. cout<<lowerequal(a,,)<<endl;
  67. }

相信再也不会担心死循环了

终极二分查找--传说十个人写九个有bug的更多相关文章

  1. POJ 1064 Cable master(二分查找+精度)(神坑题)

    POJ 1064 Cable master 一开始把 int C(double x) 里面写成了  int C(int x) ,莫名奇妙竟然过了样例,交了以后直接就wa. 后来发现又把二分查找的判断条 ...

  2. 二分查找(Java实现)

    二分查找:递归实现 public class BinarySearch { /** * @param arr 代查找的数组,需要有序 * @param left 查找区间的左界限 * @param r ...

  3. 面试官,我会写二分查找法!对,没有 bug 的那种!

    前言科普 第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间. 2019 年的你,在面试的过程中能手写出没有 bug 的二 ...

  4. 九度OJ 1349 数字在排序数组中出现的次数 -- 二分查找

    题目地址:http://ac.jobdu.com/problem.php?pid=1349 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数 ...

  5. C++11写算法之二分查找

    同样的,二分查找很好理解,不多做解释,要注意二分查找的list必须是排好序的. 这里实现了两种二分查找的算法,一种递归一种非递归,看看代码应该差不多是秒懂.想试验两种算法,改变一下findFunc函数 ...

  6. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  7. leetcode二分查找问题整理

    自从做完leetcode上的三道关于二分查找的题后,我觉得它是比链表找环还恶心的题,首先能写出bugfree代码的人就不多,而且可以有各种变形,适合面试的时候不断挑战面试者,一个程序猿写代码解决问题的 ...

  8. 二分查找实现(Jon Bentley:90%程序员无法正确实现)

    二分查找实现(Jon Bentley:90%程序员无法正确实现)作者:July出处:结构之法算法之道引言Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码.也许很多人都早已听说过 ...

  9. 分蛋糕(C - 二分查找)

    分蛋糕 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/C Description My birthd ...

随机推荐

  1. hadoop 环境搭建

    Hadoop 2.配置HDFS HA (高可用)   前提条件 先搭建 http://www.cnblogs.com/raphael5200/p/5152004.html 的环境,然后在其基础上进行修 ...

  2. 【创业积累】如何快速开发出一个高质量的APP

    [起] 今早,一个技术群里有人想快速做出一个app,然后询问技术方案,大概是这样, 拿到了200w投资,期望花20w两个月先做出一个app,包括ios,android, 先,呵呵,一下, 大概预估了一 ...

  3. SQL Profiler工具简介

    一.SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程,其作用如下: 图形化监视SQL Server查询: 在后台收集查询信息: 分析性能: 诊断像死锁之类的问 ...

  4. 根据控件Id得到控件

    在做动态获取控件时,时常需要根据Id得到控件,并对该控件进行操作,此时用 /// <summary>        /// 根据控件id得到控件        /// </summa ...

  5. objectivc-c---block

    基本格式: returnType (^blockName[num])(paramList|void) = ^returnType(paramList|void){block Body}; 标红部分可根 ...

  6. asp.net 的那点事(2、浏览器和一般处理程序)

    从今天开始我们接着来学习:asp.net中一般处理程序和浏览器的通信. 一.第一个图解: 从图解中我们看出,整个过程是:"请求---处理---响应".这个也就是经常面试的时候,面试 ...

  7. Linux下添加磁盘创建lvm分区

    shell> fdisk /dev/xvdb #### 选择磁盘 Command (m for help): m #### 帮助 Command action a toggle a bootab ...

  8. IIC 概述之24c系列存储器内存分析

    IIC 型号     容量      器件/业面寻址字节                   可寻址位       模块 24C01   128B      (1010)(A2)(A1)(A0)(0或 ...

  9. 背包问题lingo求解

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang !背包问题 题目: 8件物品   重量分别为 1,3,4,3,3,1,5,10 价值分别为 2,9 ...

  10. 酷冷至尊·毁灭者II代机箱 安装指南

    酷冷至尊·毁灭者II代机箱 安装向导