二分查找实现(Jon Bentley:90%程序员无法正确实现)
作者:July
出处:结构之法算法之道
引言
Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码。也许很多人都早已
听说过这句话,但我还是想引用《编程珠玑》上的如下几段文字:
“二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),
那么通过不断缩小包含T 的范围,最终就可以找到它。一开始,范围覆盖整个数组。将数
组的中间项与T 进行比较,可以排除一半元素,范围缩小一半。就这样反复比较,反复缩
小范围,最终就会在数组中找到T,或者确定原以为T 所在的范围实际为空。对于包含N
个元素的表,整个查找过程大约要经过log(2)N 次比较。
多数程序员都觉得只要理解了上面的描述,写出代码就不难了;但事实并非如此。如果
你不认同这一点,最好的办法就是放下书本,自己动手写一写。试试吧。
我在贝尔实验室和IBM 的时候都出过这道考题。那些专业的程序员有几个小时的时间,
可以用他们选择的语言把上面的描述写出来;写出高级伪代码也可以。考试结束后,差不多
所有程序员都认为自己写出了正确的程序。于是,我们花了半个钟头来看他们编写的代码经
过测试用例验证的结果。几次课,一百多人的结果相差无几:90%的程序员写的程序中有
bug(我并不认为没有bug 的代码就正确)。
我很惊讶:在足够的时间内,只有大约10%的专业程序员可以把这个小程序写对。但
写不对这个小程序的还不止这些人:高德纳在《计算机程序设计的艺术第3 卷排序和查
找》第6.2.1 节的“历史与参考文献”部分指出,虽然早在1946 年就有人将二分查找的方法
公诸于世,但直到1962 年才有人写出没有bug 的二分查找程序。”——乔恩·本特利,《编
程珠玑(第1 版)》第35-36 页。
你能正确无误的写出二分查找代码么?不妨一试。
348
二分查找代码
二分查找的原理想必不用多解释了,不过有一点必须提醒读者的是,二分查找是针对的
排好序的数组。OK,纸上读来终觉浅,觉知此事要躬行。我先来写一份,下面是我写的一
份二分查找的实现(之前去某一家公司面试也曾被叫当场实现二分查找,不过结果可能跟你
一样,当时就未能完整无误写出),有任何问题或错误,恳请不吝指正:
//二分查找V0.1 实现版
//copyright@2011 July
//随时欢迎读者找bug,email:zhoulei0907@yahoo.cn。
//首先要把握下面几个要点:
//right=n-1 => while(left <= right) => right=middle-1;
//right=n => while(left < right) => right=middle;
//middle 的计算不能写在while 循环外,否则无法得到更新。
int binary_search(int array[],int n,int value)
{
int left=0;
int right=n-1;
//如果这里是int right = n 的话,那么下面有两处地方需要修改,以保证一一对应:
//1、下面循环的条件则是while(left < right)
//2、循环内当array[middle]>value 的时候,right = mid
while (left<=right) //循环条件,适时而变
{
int middle=left + ((right-left)>>1); //防止溢出,移位也更高效。同时,每次循环
都需要更新。
if (array[middle]>value)
{
right =middle-1; //right 赋值,适时而变
}
else if(array[middle]<value)
{
left=middle+1;
}
else
return middle;
//可能会有读者认为刚开始时就要判断相等,但毕竟数组中不相等的情况更多
//如果每次循环都判断一下是否相等,将耗费时间
}
return -1;
349
}
简单测试下,运行结果如下所示(当然,一次测试正确不代表程序便0 bug 了,且测试
深度远远不够):
测试
也许你之前已经把二分查找实现过很多次了,但现在不妨再次测试一下。关闭所有网页,
窗口,打开记事本,或者编辑器,或者直接在本文评论下,不参考上面我写的或其他任何人
的程序,给自己十分钟到N 个小时不等的时间,立即编写一个二分查找程序。独立一次性
正确写出来后,可以留下代码和邮箱地址,我给你传一份本blog 的博文集锦CHM 文件&&
十三个经典算法研究带标签+目录的PDF 文档(你也可以去我的资源下载处下载:
http://download.csdn.net/user/v_july_v)。
350
当然,能正确写出来不代表任何什么,不能正确写出来亦不代表什么,仅仅针对Jon
Bentley 的言论做一个简单的测试而已。下一章,请见第二十六章:基于给定的文档生成倒
排索引的编码与实践。谢谢。
总结
本文发表后,马上就有很多朋友自己尝试了。根据从朋友们在本文评论下留下的代码,
发现出错率最高的在以下这么几个地方:
1. 注释里已经说得很明白了,可还是会有不少朋友犯此类的错误:
1. //首先要把握下面几个要点:
2. //right=n-1 => while(left <= right) => right=middle-1;
3. //right=n => while(left < right) => right=middle;
4. //middle 的计算不能写在while 循环外,否则无法得到更新。
2. 还有一个最最常犯的错误是@土豆:
middle= (left+right)>>1; 这样的话left 与right 的值比较大的时候,其和可能溢出。
各位继续努力。
updated:各位,可以到此处0 积分下载本blog 最新博文集锦第6 期CHM 文件:
http://download.csdn.net/detail/v_july_v/4020172。

二分查找实现(Jon Bentley:90%程序员无法正确实现)的更多相关文章

  1. page61-将二分查找重写为一段面向对象的程序

    1 将二分查找重写为一段面向对象的程序 (用于在整数集合中进行查找的一种抽象数据类型) public class StaticSETofInts [API] StaticSETofInts(int[] ...

  2. 90%程序员都没有完全答对Cookie和Session的区别

    我在做面试官的时候,曾经问过很多朋友这个问题: Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等. ...

  3. 入职半年多,Guide哥总结了这些帮助你领先90%程序员的好习惯!

    大家好,我是 Guide 哥,这篇文章还是不分享技术文章了,我想简单聊聊一些程序员的好习惯. 其实自己写这篇文章还是很忐忑的,毕竟自己算不上一个优秀的程序员,但也不是那么差.大学学习编程 4 年,工作 ...

  4. 「mysql优化专题」90%程序员没听过的存储过程和存储函数教学(7)

    一.MYSQL储存过程简介(技术文): 储存过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时 ...

  5. 「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)

    目录(技术文) 多关于索引,分为以下几点来讲解: 一.索引的概述(什么是索引,索引的优缺点) 二.索引的基本使用(创建索引) 三.索引的基本原理(面试重点) 四.索引的数据结构(B树,hash) 五. ...

  6. mysql优化专题」90%程序员都会忽略的增删改优化(2)

    补充知识点:操作数据语句优化的认识 通常情况下,当访问某张表的时候,读取者首先必须获取该表的锁,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作). ...

  7. 全世界只有我们Erlang程序员是正确的

    http://www.aqee.net/erlang-solving-the-wrong-problem/ 对某些程序来说是的,但对大多数程序来说不是.对大多数程序来说24个CPU中只有一个被利用.C ...

  8. 【15】-java实现二分查找

    二分查找在面试中经常被遇到,这个方法十分优雅 介绍 二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T的范围,最终就可以找到它.一开始,范围覆盖整个数组 ...

  9. Find Minimum in Rotated Sorted Array 典型二分查找

    https://oj.leetcode.com/problems/find-minimum-in-rotated-sorted-array/ Suppose a sorted array is rot ...

随机推荐

  1. Camel In Action 阅读笔记 第一章 认识Camel 1.1 Camel 介绍

    1.1 Camel 介绍 Camel 是一个为了您的项目集成变得高效有趣的集成框架,Camel 项目在2007年初开始的,相对来说它还比较年轻,但它已然是一个非常成熟的开源项目,它所使用的是Apach ...

  2. 在WP8上搭建cocos2d-x开发环境

    在WP8上搭建cocos2d-x开发环境 转自:https://github.com/koowolf/cocos-docs/blob/master/manual/framework/native/in ...

  3. Java并发编程:Java ConcurrentModificationException异常原因和解决方法

    Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...

  4. MVC个人认为的终极分页

    //传入要查询的字段,查询条件(例如根据姓名查看数据的数据筛选),按照什么排序,页码,信息条数 //T:要操作的类型 //Tkey:根据什么类型来排,ID的话返回的是int类型,但是name的话又会返 ...

  5. Gym 101064 D Black Hills golden jewels (二分)

    题目链接:http://codeforces.com/gym/101064/problem/D 问你两个数组合相加的第k大数是多少. 先sort数组,二分答案,然后判断其正确性(判断过程是枚举每个数然 ...

  6. Uncaught TypeError: Object #<Object> has no method 'fancybox'

    Uncaught TypeError: Object #<Object> has no method 'fancybox' 2011-10-24 16:51:19|  分类: html|举 ...

  7. php二叉树算法

    二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒.二叉树的第i层至多有2^{i-1}个结点:深度为k的二叉树至多有2^k-1个结点:对任何一棵二叉树T,如 ...

  8. MVC 小常识

    什么是MVC (模型 视图 控制器)? MVC是一个架构模式,它分离了表现与交互.它被分为三个核心部件:模型.视图.控制器.下面是每一个部件的分工: 视图是用户看到并与之交互的界面. 模型表示业务数据 ...

  9. jsp与El,jstl知识点总结归纳

    jsp与El,jstl知识点总结归纳 jsp部分 一.jsp的三大指令 page ,include,taglib 1.jsp中的page指令 <% page %>-设置jsp 例如: &l ...

  10. extjs表格下的分页条——Ext.grid.Panel 的 pagingtoolbar

    两种分页条:每页固定条数的分页条 和 自定义选择每页内容条数的分页条 一.每页固定条数的分页条 这种样式的-- dockedItems: [{ xtype: 'pagingtoolbar', stor ...