icebirds吧 关注:33贴子:2,025
  • 4回复贴,共1

【20150128◇心情】二分法——程序真的没那么容易写

只看楼主收藏回复

二分法是很多数据结构和算法课的第一课。
问题非常简单,在一个有序的列表或数组中,例如 [1,2,3,5,6,7,9,11,20] ,如何快速找到一个元素在这个列表中是否存在,如存在,在什么位置?很多人看了这个问题会哈哈大笑,这还不简单,你说找5,我一眼就看到了。好吧,我承认电脑在上面这个例子里,没人用眼睛看来的直接(虽然它实际上计算时比你更快)。可问题是,电脑没这个能力,如果是最笨的办法,就只能让它从头到尾一个一个去找,但如果这个列表有几万甚至几十万个元素呢?这时这么找就非常愚蠢了。怎么办?最简单的算法就是二分法。还是上面的例子,先找到列表最中间的元素,如果比要找的大,下一步就从左侧一半的中间找,否则就从右边找,这样一半一半地找下去,直到找到,或者一直到不能再切分后还是找不到。整个计算就结束。
【待续】


IP属地:海南1楼2015-01-28 14:37回复
    「接上」
    看了上面说的算法,看起来也没那么难,稍微懂点编程的人就应该知道怎么做了吧?不就是先找到最中间的,然后判断大小,接着再找下一个中间,不断分下去直到找到为止吗?简单,三分钟搞定(使用中文伪码描述算法):
    目标数字 =获取值
    最小边界= 0
    最大边界=数组长度/2
    循环:
    中间点 = 对(最大边界+最小边界/2)取整
    如果 中间点>目标数字:
    最大边界=中间点
    或者 中间点<目标数字:
    最小边界=中间点
    或者 中间点=目标数字:
    找到目标值,结束循环
    循环尾
    可是,事情真的就那么简单吗?看看下面这个数组: [1,2,3,5,6,8,9] 如果让你在这个数组里找到一个7,你的程序还有效吗?出现什么问题了?哦,这个数组里压根没有7这个数字,于是,在找不到目标的情况下,程序被迫一直循环下去了,没有尽头。也就是说,陷入了死循环。
    好吧,那么,我们再把程序完善一下。
    目标数字 =获取值
    最小边界= 0
    最大边界=数组长度/2
    循环:
    ===== 增加如下语句 =====
    如果 最大边界-最小边界<=1 并且 最大边界和最小边界都不同于目标值:
    数组中没有目标数字,结束循环。
    ===== 增加逻辑结束 =====
    中间点 = 对(最大边界+最小边界/2)取整
    如果 中间点>目标数字:
    最大边界=中间点
    或者 中间点<目标数字:
    最小边界=中间点
    或者 中间点=目标数字:
    找到目标值,结束循环
    循环尾
    好吧,你解决了我们提出的那个问题,可是,问题又来了:还是这个数组: [1,2,3,5,6,8,9] ,找11这个数字,于是,你的程序找了半天之后,把中间点一口气移到了倒数第二项,终于确定了数组中没有这个数字,可是,如果这个数组很长,岂不是要浪费很多时间去查找?好蠢……一开始就判断一下查找目标是否超过数组边界就可以了嘛。于是,又增加逻辑。在这之后,我们又遇到了另一个问题: [1,2,3,3,5,5,6,8,8,9] 这个数组中,查找8这个数字。好吧,我知道肯定能查找出来,可是问题是,这里有两个8,你确定查找全了吗?有时我们不需要全部查找出来,可很多时候,是需要的。那么,问题就又出现了。我们又得对数组里有相同数据的情况进行处理。接着,又要想法优化程序,去掉不必要的步骤……
    一个听起来十分简单的二分法查找,真正实现起来,是如此的让人头大。而实际的程序开发中,遇到的情况,远比这个学术性问题复杂的太多,所以,当我们经常听人说“程序员效率低了就是偷懒”、“这么简单的东西都做不好”等等,心里最大的想法,就是特么的赶紧改行,不特么干这个苦逼职业了。


    IP属地:海南2楼2015-02-03 21:29
    回复
      广告
      立即查看
      二分法是很多数据结构和算法课的第一课。
      问题非常简单,在一个有序的列表或数组中,例如 [1,2,3,5,6,7,9,11,20] ,如何快速找到一个元素在这个列表中是否存在,如存在,在什么位置?很多人看了这个问题会哈哈大笑,这还不简单,你说找5,我一眼就看到了。好吧,我承认电脑在上面这个例子里,没人用眼睛看来的直接(虽然它实际上计算时比你更快)。可问题是,电脑没这个能力,如果是最笨的办法,就只能让它从头到尾一个一个去找,但如果这个列表有几万甚至几十万个元素呢?这时这么找就非常愚蠢了。怎么办?最简单的算法就是二分法。还是上面的例子,先找到列表最中间的元素,如果比要找的大,下一步就从左侧一半的中间找,否则就从右边找,这样一半一半地找下去,直到找到,或者一直到不能再切分后还是找不到。整个计算就结束。
      看了上面说的算法,看起来也没那么难,稍微懂点编程的人就应该知道怎么做了吧?不就是先找到最中间的,然后判断大小,接着再找下一个中间,不断分下去直到找到为止吗?简单,三分钟搞定(使用中文伪码描述算法):
      目标数字 =获取值
      最小边界= 0
      最大边界=数组长度/2
      循环:
      中间点 = 对(最大边界+最小边界/2)取整
      如果 中间点>目标数字:
      最大边界=中间点
      或者 中间点<目标数字:
      最小边界=中间点
      或者 中间点=目标数字:
      找到目标值,结束循环
      循环尾
      可是,事情真的就那么简单吗?看看下面这个数组: [1,2,3,5,6,8,9] 如果让你在这个数组里找到一个7,你的程序还有效吗?出现什么问题了?哦,这个数组里压根没有7这个数字,于是,在找不到目标的情况下,程序被迫一直循环下去了,没有尽头。也就是说,陷入了死循环。
      好吧,那么,我们再把程序完善一下。
      目标数字 =获取值
      最小边界= 0
      最大边界=数组长度/2
      循环:
      ===== 增加如下语句 =====
      如果 最大边界-最小边界<=1 并且 最大边界和最小边界都不同于目标值:
      数组中没有目标数字,结束循环。
      ===== 增加逻辑结束 =====
      中间点 = 对(最大边界+最小边界/2)取整
      如果 中间点>目标数字:
      最大边界=中间点
      或者 中间点<目标数字:
      最小边界=中间点
      或者 中间点=目标数字:
      找到目标值,结束循环
      循环尾
      好吧,你解决了我们提出的那个问题,可是,问题又来了:还是这个数组: [1,2,3,5,6,8,9] ,找11这个数字,于是,你的程序找了半天之后,把中间点一口气移到了倒数第二项,终于确定了数组中没有这个数字,可是,如果这个数组很长,岂不是要浪费很多时间去查找?好蠢……一开始就判断一下查找目标是否超过数组边界就可以了嘛。于是,又增加逻辑。在这之后,我们又遇到了另一个问题: [1,2,3,3,5,5,6,8,8,9] 这个数组中,查找8这个数字。好吧,我知道肯定能查找出来,可是问题是,这里有两个8,你确定查找全了吗?有时我们不需要全部查找出来,可很多时候,是需要的。那么,问题就又出现了。我们又得对数组里有相同数据的情况进行处理。接着,又要想法优化程序,去掉不必要的步骤……
      一个听起来十分简单的二分法查找,真正实现起来,是如此的让人头大。而实际的程序开发中,遇到的情况,远比这个学术性问题复杂的太多,而所谓的程序BUG或者漏洞,其产生的原因,就是在极端情况下,由于程序处理不够完全而出现的计算失误,如同上面例子里那个永远都找不到的7,当程序出现这种失误的时候,这个程序究竟会干什么,连程序员自己都无法预料,只有它们真正出现了,才会发现它究竟会干些什么莫名其妙的事情,对程序的威胁小的,就叫做BUG,有的BUG,特别是在游戏里,还会被人当作彩蛋(80后的老玩家相信很多都对FC游戏机上的热血系列大量的BUG有记忆吧); 对程序产生较大威胁甚至巨大威胁可能会导致程序崩溃或者安全问题的,就叫做漏洞。一个软件产品,不论是网站,还是游戏,或者是在电脑上运行的办公软件等等,大多是以大量类似上面提到的二分法这样的微小逻辑去组合而成,涉及到了各种逻辑计算成千上万,甚至在大型软件套装中存在上亿这样的逻辑都不稀奇,软件规模越大,可能被遗漏的问题,也就越多。而有时,我们看到的一个简单功能,例如你在下面打几个字回复一个帖子,涉及到的基本单元计算,都要几十上百。这些单元计算,每个都需要测试。有时你看到一个程序员很快就搞定了一个什么东西,很可能是这个东西以前就有个差不多的,只需要简单改改,组装一下就行了,可很多时候,并非如此。一个高效的程序开发团队,一定是经过了长时间技术积累,把平时能用到的各种细小单元计算全部都整理打磨完毕,随时可以拿来像搭积木一样使用的。如果从头开始开发,即便是谷歌、微软、百度这样的软件巨头,也没可能快速搞定。我们电脑上使用的每一个功能,都是无数程序员多年以来呕心沥血积累完成的。
      程序开发,绝对没有那么容易写。哪怕你用的是号称再高级的语言也一样……
      综上,当我们经常听人说“程序员效率低了就是偷懒”、“这么简单的东西都做不好”等等,心里最大的想法,就是特么的赶紧改行,不特么干这个苦逼职业了。


      IP属地:海南3楼2015-02-03 21:42
      回复
        既然那么有才,为何还要婚姻?


        4楼2015-02-06 05:32
        收起回复