二分搜索算法和快速排序算法

二分搜索算法

理论:

         二分搜索算法用于针对已排序的集合进行搜索。

它的原理是:

1,  找到排序数组的中间元素,如果它匹配目标值,那么就返回它在数组中的索引。

2,  如果没有找到,那么判断中间值比目标值大还是小,

如果中间值比目标值大,那么就对第一个元素到middle-1的元素递归这个过程。

如果中间值比目标值小,那么就对middle+1到最后一个元素。

3,  如果结束的索引小于开始的索引,返回-1,表示没有找到。

4,  如果子集合有2个元素,那么各自比较。因为Java的整数除法会舍弃小数,如果数组只有2个元素,那么middle值一直都是第一个元素。

经过上述的递归过程,最终将返回匹配元素的索引,或者是-1,表示找不到。

 

         二分搜索算法之所以速度快,是因为它每次可以把数组切分成两半,每次递归调用都能去除一半数据,而不用匹配每一个数据。

 

代码:

         下面是代码,逻辑清楚,代码简单。

 

    public static int binarySearch(int[] array,int start,int end,int value){

       int middle=(start+end)/2;

       if(end<start){

           return -1;

       }

       if(end==(start+1)){

           if(array[start]==value){

              return start;

           }else if(array[end]==value){

              return end;

           }

          

       }else if(array[middle]==value){

           return middle;

       }else if(value>array[middle]){

           return binarySearch(array,middle+1,end,value);

       }else if(value<array[middle]){

           return binarySearch(array,start,middle-1,value);

       }

       return -1;

   

    }

 

         上述代码稍加改变,就可以排序任意类型。如使用泛型,然后加上对Comparable接口的实现,即可。

 

快速排序算法

         二分搜索算法确实非常快,但是它只能用于已排序数组。如果数组未排序呢,该怎么办呢?简单,先用快速排序算法进行排序,然后再用二分搜索进行搜索。

         先排序再搜索,要比匹配每一个元素快得多。搜索引擎,数据库索引也都使用了对数据集合的排序技术,这样搜索数据才会快速。

 

理论:

         最慢,也是最容易想到的排序算法是插入排序算法:

1,  遍历数组,找出最小的元素,把它放到第一个元素。

2,  循环查找未排序的数组,直到整个数组排序。

这需要2个嵌套的循环,意味着它的效率是O(n^2);

之所以插入排序的效率如此之地,是因为要找出整个数组中最小的数据,需要遍历整个数组的元素。

而插入排序聪明就聪明在它不查找整个数组最小、次小…的元素,而是每次仅仅把小于某个元素的值移到一边,通过迭代最终自动实现排序。这就大大节约了排序所需的计算步骤。

 

         快速排序算法的理论:

1,  如果S中的元素个数是0或者1,那么返回。

2,  选取S中的任一元素v,称为中心点。

3,  将S集合中的元素分为2个部分:L={小于pivot 的元素+ pivot }和R={大于或者等于pivot的元素}。

4,  返回L和R。

我们使用Java使用的是就地排序的方式,因此不需要返回值。

因为Java是一种可以修改变量的语言,用函数式语言的术语来说,就是有“副作用”。我们利用这个副作用直接修改作为参数的Array,不需要返回值。

 

 

代码:

     * 快速排序,有副作用   从小到大

     * @param array

     * @param start

     * @param end这是最后一个元素的索引,第一次调用应该是array.length-1

     */

    public static void quickSort(int[] array,int start,int end){

       //有可能造成start>end   因为递归调用时j+1,可能引起j比end还大1。  另外如果数组是空的,或者输入错误也会出现这种情况

       if(end<=start){

           return;          

       }else {

           //取中间元素为中心点,然后移到最右边

           int sign=(start+end)/2;

           int tmp=array[end];

           array[end]=array[sign];

           array[sign]=tmp;

           int j=start;

           for(int i=start;i<=end-1;i++){ 

              //小于的元素和标记互换,等于的不能互换,否则会形成死循环

              if(array[i]<array[end])  {                

                   tmp=array[i];

                   array[i]=array[j];

                   array[j]=tmp;

                   j=j+1;

              }         

           }

           //把标记元素和第一个>=它的元素位置互换,这样数组就分成2个部分,一个部分比中心值小,一个部分比中心值大。

           tmp=array[j];

           array[j]=array[end];

           array[end]=tmp;

           quickSort(array,start,j);

           quickSort(array,j+1,end);

       }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值