排序算法(3)

快速排序

快速排序可能是应用最广泛的算法了。快排流行的原因在于实现简单、并且适用于各种不同的输入数据,因此在一般的应用中比其他排序算法都要快很多。快排的优点在于其是原地排序,不向归并至少需要建立一个和排序数组大小一样的数组,并且快排的时间复杂度和NlgN成正比

基本思想

快速排序是一种分治的排序算法。它将一个数组分成两个数组,将两部分独立的排序,这时候就会想到归并排序了,好像两者的思想是一样的,但实际上它们是互补的:归并排序将数组分为两个子数组,并将有序的子数组归并已将整个数组进行排序;而排序排序是将数组排序的方式则是当两个子数组都有序时整个数组也就自然有序了。在第一种情况中,递归调用发生在处理整个数组之前;在第二中情况中,递归调用发生在处理整个数组之后。在归并排序中,一个数组被分为两半;在快速排序中,切分的位置取取决于数组的内容。

算法实现

package chapter2.section1;

/**
* @ClassName Quick
* @Descrition TODO
* @Date 2022/4/22 23:01
* @Created by 小叶
*/
public class Quick {
   public static void main(String[] args) {
       //主程序,执行程序
  }
   //比较部分
   private static boolean less(Comparable v, Comparable w){
       return v.compareTo(w) < 0;
  }
   //交换部分
   private static void exch(Comparable[] a, int i, int j){
       Comparable t = a[i];
       a[i] = a[j];
       a[j] = t;
  }
   //打印数组对象
   private static void show(Comparable[] a){
       for (int i = 0; i < a.length; i++) {
           System.out.print(a[i]+" ");
      }
       System.out.println();
  }
   //判断是否有序
   public static boolean isSorted(Comparable[] a){
       for (int i = 1; i < a.length; i++) {
           if(less(a[i],a[i-1])){
               return false;
          }
      }
       return true;
  }
   
   public static void sort(Comparable[] a,int lo , int hi){
       //递归结束条件
       if (hi <= lo) return;
       //先进行处理
       int j = partition(a, lo, hi);
       //左边递归
       sort(a, lo ,j-1);
       //右边递归
       sort(a,j+1, hi);
  }

   private static int partition(Comparable[] a, int lo, int hi) {
       //记录一下左右位置
       int i = lo, j = hi+1;
       //挑选第一个元素作为对比元素
       Comparable v = a[lo];
       while(true){
           //左边比v大的元素
           while(less(a[++i],v)) if(i == hi) break;
           //右边比v小的元素
           while(less(v,a[--j])) if(j == lo) break;
           //防止边界
           if(i >= j) break;
           //进行交换
           exch(a, i,j);
      }
       //最后对比元素插入
       exch(a, lo, j);
       //返回
       return j;
  }

}

可以看出,快排的关键在于切分,这个过程使得数组满足下面三个条件

  1. 对于某个j,a[j]已经排定

  2. a[lo]到a[j-1]的元素都不大于a[j]

  3. a[j+1]到a[hi]的元素都不小于a[j]

因此,通过这样的递归,从而获得最终的排序结果,请注意,这里是先对数组进行处理,然后在递归,递归过程中用到的额外空间复杂度,也是比较低的。

总结

优秀的快排,特殊场景需要改进。

posted @ 2022-04-22 23:23  叶nil  阅读(386)  评论(1编辑  收藏  举报