分分钟掌握快速排序(Java / Scala 实现)

今天我们来学习一种不浪费空间、效率还非常高的排序算法——快速排序。

算法思想

快速排序的基本思想——分治法。

1. 选取基准数(pivot):选数组中的第一个或者中间一个。

2. 分区:将数组中比基准数小的放的左边,比基准数大的放到右边。

3. 递归:对左右分区重复1、2操作。

过程描述

有这样一个数组arr,长度为11。

13, 34, 23, 8, 12, 17, 12, 42, 4, 9, 19

1)  以第一个数13为基数。我们指定两个变量i(i=0)、j(j=10)分别指向数组两端。我们将第一个数赋给pivot,pivot = arr[i]。这时需要找一个比pivot小的数填充arr[i]。

[Nil], 34, 23, 8, 12, 17, 12, 42, 4, 9, 19            pivot = 13 (i=0,j=10)

2)  首先移动j,从右向左移动,直到找到第一个比pivot小的数。当j=9时,arr[j] < pivot,将arr[j]赋值给arr[i]。此时有需要找一个大于或等于pivot的数,来填充arr[j]。

9, 34, 23, 8, 12, 17, 12, 42, 4, [Nil], 19            pivot = 13  (i=0, j=9)

3)  从左向右移动i,直到找到第一个大于等于pivot的数。当i=1时,arr[i] > pivot,将arr[i]赋值给arr[j]。再找一个比pivot小的数来填充arr[i]。

9, [Nil], 23, 8, 12, 17, 12, 42, 4, 34, 19            pivot = 13 (i=1, j=9)

4)  按照这个规律一直推下去直到i==j。就将pivot赋给arr[i](或者arr[j])。

9,4,23,8,12,17,12,42,[Nil],34,19            pivot = 13 (i=1, j=8)

9,4,[Nil],8,12,17,12,42,23,34,19            pivot = 13 (i=2, j=8)

9,4,12,8,12,17,[Nil],42,23,34,19            pivot = 13 (i=2, j=6)

9,4,12,8,12,[Nil],17,42,23,34,19            pivot = 13 (i=5, j=6)

第一次循环的结果是9, 4, 12, 8, 12, 13, 17, 42, 23, 34, 19。pivot(13)将数组分成了左右两个分区。

5)  利用递归的方式,对左右两个分区做上述操作。


代码实现

先看Java代码实现,结合上面的过程描述以及代码里面的注释,相信不难看明白。

public static void quickSort(int arr[], int start, int end) {
    if (start < end) {
    	int pivot = arr[start];
        int i = start, j = end;
        while (i < j) {
            // 从右向左移动j,直到找到第一个小于pivot的数
            while(i < j && arr[j] >= pivot) 
		        j--;  
            if(i < j) 
		        arr[i++] = arr[j];
			
            // 从左向右移动i,直到找到第一个大于等于pivot的数
            while(i < j && arr[i] < pivot) 
		        i++;  
            if(i < j) 
		        arr[j--] = arr[i];
        }
        // 直到i == j,遍历结束,将pivot赋给arr[i]
        arr[i] = pivot;
        
        // 递归调用 
        quickSort(arr, start, i - 1); 
        quickSort(arr, i + 1, end);
    }
}

再看用Scala如何实现

def sortScala(xs: Array[Int]): Array[Int] = {
   if (xs.length <= 1) xs
   else {
      val pivot = xs(xs.length / 2)
      Array.concat(
         sortScala(xs filter (pivot >)),
         xs filter (pivot ==),
         sortScala(xs filter (pivot <)))
   }
}

哇哦,简洁程度简直亮瞎双眼。只不过与我们前面描述过程稍微有些差别。这里是将分区分成大于、小于、等于三部分,每次都对递归结果做个合并就OK了,缺点就是它需要更多的转换空间。

如果你想了解scala,可以参照我的另一篇博客Scala极速入门

总结

快速排序是基于分治法、不稳定的排序算法。时间复杂度平均情况为O(n*logn),最差情况为O(n^2)。

转载于:https://my.oschina.net/mup/blog/362210

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值