图解Java快速排序(基于数组)

最近想弄明白快速排序的实现原理,直接看代码有点迷糊,所以从网上找了图解,好明白得多。现附上链接:

http://zzqrj.iteye.com/blog/572620

转载既然注明出处了,就厚颜无耻的列出其代码实现和图解吧!
因为原文言简意赅,我这里加了一些自己的理解,可能废话,但起码有益于我自己理解~

快速排序采用分而治之的思想,实现步骤是:

  1. 确定中心元素, 将中心元素与表的第一个元素交换
    索引smallIndex初始化为表中第一个元素,指向小于中心元素的lower sublist的最后一个元素(见图解第2步示意)。
  2. 对表中剩余元素
    剩余元素指的是除了中心元素、已经被划分到lower sublist和upper sublist之外剩余的元素。
    如果当前元素(index所指向的元素,剩余元素中下标最小的元素,见图解第2步示意)小于中心元素,则需要将它挪到lower sublist这一阵营。操作步骤是:
    a.smallIndex加一,挪个位置出来;
    b.交换当前元素 和由 smallIndex所指向的数组元素。
    因为,smallIndex挪出的位置被upper sublist的第一个元素占用着,这么一交换,upper sublist的第一个元素就成了upper sublist阵营的的最后一个元素,这也难怪说快速排序不稳定。
    如果当前元素 大于中心元素,只需将当前元素index向后挪动一位,这个当前元素自然落入upper sublist阵营(见图解第3步示意)。
  3. 交换第一个元素(即中心元素)和由smallIndex指向的数组元素
    当所有元素都划分到lower sublist和upper sublist两大阵营,就要将此时居于首位的中心元素放回到它应该在的位置,即两大阵营正中间,让左边的数都比它小,右边的数都比它大(见图解第4步和第5步示意)
  4. 这一轮排序结束了,然后分别针对lower sublist和upper sublist再次进行类似的操作。直到lower和upper被分解为最小粒度——一个元素。

快速排序图解(基于数组)

最后再附上这位前辈的代码(真的是前辈,因为是2010年的博客。。):

public class QuickSort {

public static int partition(int arr[], int start, int end) {
    int pivot;
    int index, smallIndex;

    swap(arr, start, (start + end) / 2);
    pivot = arr[start];// center element
    smallIndex = start;

    for (index = start + 1; index <= end; index++) {
        if (arr[index] < pivot) {
            smallIndex ++ ;
            swap(arr, smallIndex, index);
        }
    }
    swap(arr, start, smallIndex);//recover center element’position
    return smallIndex;
}

public static void swap(int[] arr, int n1, int n2) {
    int temp;
    temp = arr[n1];
    arr[n1] = arr[n2];
    arr[n2] = temp;
}

public static void quickSort(int arr[], int start, int end) {
    int pivotLocation;
    if (start < end) {
        pivotLocation = partition(arr, start, end);
        quickSort(arr, start, pivotLocation - 1);//recursion
        quickSort(arr, pivotLocation + 1, end);
        }
    }
}

以上是快速排序涉及的基本的技术点,关于时间复杂度、空间复杂度的分析,以及使用场合、在Android开发中的应用、与其他排序方式的比较,后续再补上。


快排算法的特点:
  • 实用性强

很多实际的项目中使用了快排算法。但通常对算法都进行了调整(tuning),比如Java.util.Arrays类中的sort函数就使用了快排算法,但使用了双参考值(Dual-Pivot Quicksort)等一些改进措施。由于快排算法为递归算法,可以用循环代替递归函数调用,改进性能。

  • 不需要额外空间

可以将数组中的数据直接交换位置实现排序,所以理论上不需要额外的空间。

  • 升序排列

  • 不稳定排序

时间复杂度:
  • 平均情况:O(nlgn)
  • 最坏情况:O(n*n),发生在当数据已经是排序状态时
使用泛型实现快排算法:
  • 对任意类型数组进行排序。如果为对象类型数组,则该对象类型必须实现Comparable接口,这样才能使用compareTo函数进行比较。

注:对比了前人的代码实现,发现思想一样,实现都略有不同,涉及到代码的包装、处理对象的多态、边界条件的处理细节等。以后有心得再扩充对比。

参考链接:http://my.oschina.net/u/1382972/blog/169747 (2013年的博客)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值