研究二分搜索算法

来源:互联网 发布:陌陌夜神营销软件 编辑:程序博客网 时间:2024/04/30 06:46

二分搜索的深入研究

(特别提醒,我喜欢大家关注文章本身,而不是我的排版~,虽然咱的文章没人看,但也要友好提示~)
直接进入正题,节约大家时间,二分搜索简单的我都不好意思来写,但是为了循序渐进的来,还是一步一个脚印子实在!哈哈

先说下为什么要用二分搜索,直接通俗的例子就是~你和我玩游戏,如果你心里想出来一个数字,让你猜我想的是多少?你每次猜过,我都提示你,你所猜的数字与我想的
数字的大小关系,比如我们俩规定我想一个100以内的数字,比如我想的是37,你首先会猜50,我说大了,你猜25,我说小了,直至你将我所猜的数字答出为止。
  • 这肯定要比你直接从1问到100来猜我所想的数字快的多的多。那么如果你每次猜中间,大约几次能猜出答案呢?
很简单我们粗略来算,太精确也没多少意义,100>2^6(我真心不会排版!100大于2的6次方) 100<2^7。
关键的一句是① ,它表明什么?由于100小于128,对于128来说,你运气再差也应该在7次内找到我所想的数字,因为每次二分切割128都会除以2,那么他除以2七次也就是等于1,也就是说经过7次筛选就剩下一个数字,那么这一个就是答案。
所以我们可以粗略的来统计,如果按照这样的查找,N个已排序的数据来说  2^m-1<N<=2^mm的取值范围我就不详细写了,数学内容我尽量写出核心而不是严谨,太严谨就太枯燥了。 由于对数函数lg(以后我的lg表示以2为底)是单调递增的函数(f(x)单调递增就是说p>q则f(p)>f(q),  f(p)>f(q)则p>q,可以下个软件看下对数函数的图形表示,不解释了。),所以 lg2^m-1<lgN<=lg2^m ==>>  m-1<lgN<=m 所以就得出啥子呢?最多查找数字为m次

定理哦亲~二分查找在N(设N为 2^m-1<N<=2^m)个排序的数据中查找一个元素最多需要m次。

上取整函数为:ceiling,也就是最多需要ceiling(lgN)次~ 下次你可以直接拿来用 而不是思前想后,因为我们证明啦。(虽然不是数学的那种形式化的证明,而且也不是非常严谨,但是对于理解足够了。)
也就是说 就算有2^32个已排序的数据,我们也可以在32次之内找出他,运气烂到渣也不过32次就找到了!这就是二分查找的威力之所在,快!快!快!恕我才疏学浅,我没找到比它更快的查找。如果你知道,请告诉我,互相学习~
缺点很明显喽,数据必须排好序!这也是我们学习排序算法的源动力啊。
我先给出二分搜搜的代码把,java写着比较简单,不用考虑一些内存等杂七杂八的问题。
public static int binary_search(int key, int[] a) {//a是排好序的数组,key要找的在数组中的索引,int是返回key在数组索引,没找到返回-1
int lo = 0; //做个游戏,你猜我心里想的数~ 咱俩规定好,我想的数字的范围~ 自然要初始化这个范围喽,lo和hi
int hi = a.length - 1;
while(lo<=hi) {//这个是个关键,等会解释
//为了便于理解,我在这里加一句循环的不变量(也就是说每次循环我的这句话都成立!):
//如果这个key在数组中 那么就必然在[lo,hi]这个区间中,你自己分析,每次循环这个不变量都在缩小
    int mid = lo+(hi-lo)/2;//你脑子里肯定会想,既然要猜就猜中间那个吧~
    if(key<a[mid]) hi = mid-1; //我回答的是小啦~ 你会咋样?肯定范围缩小啦
    else if(key>a[mid]) lo = mid+1;//我回答的是大啦~ 我希望我的注释对于你来说是多余的~
    else return mid; //如果相等就返回了
}
return -1;//前面竟然没返回,那肯定是没有喽。
}

循环退出的条件证明:首先你或许会说,如果这个lo>hi了 待查数据的所在的区间肯定是不存在,自然循环就结束了。可是我问你,这个循环会出现死循环吗?也就是说,随着这个循环不停的运行如果数据不存在lo会大于hi吗?

看下代码不就知道啦,如果数据不存在,则每次一的循环都会增加lo 或者减少hi。当lo>hi时,就肯定不存在这个区间中了。总有一天~~会结束!
文中有错得话,强烈欢迎提出,这也是我写博客的核心源动力之一。以后排版会加强,我们先研究思想,再谈算法。
下集我们讨论下:递归吧,我想我对二分搜索还有递归的实现,以及还有很多话要说,还是有点自己的见解在里面的,欢迎来探讨~
下次博客的内容我先说下,你们也好自己研究一下,然后我们探讨,这样提高的快!真心的快!(我的自学经验,毫无保留的说)
第一,实现二分查找的递归算法。
第二,如果数组中(暂时先研究数组吧。。)当然是已经排好序的,我们带查得元素 有重复,比如:0,1,2,3,4,4,4,4,8,9我们目前的二分查找只能随机的找出4的索引,我们要实现能找出这个元素第一次出现的位置,比如这里 位置就是第五个元素,而不是随意的 5 6 7 8位置。
第三,汉诺塔的递归实现,网上资料很多。
第四,约瑟夫的问题程序的解决(你会看到代数分析会让问题有奇解)
第五,欧几里得算法,soeasy~
上面五个问题,大家可以上网查资料,来学习,然后我们探讨~目的只有一个,互相学习,快速进步~