十大排序算法快速排序之Java实现

傷城~ 2023-02-28 01:54 260阅读 0赞

快速排序

快速排序(Quick Sort)是对冒泡排序的一种改进,采用的是分治策略(一般与递归结合使用),以减少排序过程中的比较次数。

快速排序在1960年由查尔斯·安东尼·理查德·霍尔(Charles Antony Richard Hoare,缩写为C. A. R. Hoare)提出,昵称为东尼·霍尔(Tony Hoare)。

算法步骤

  1. 从数组中选择一个轴点元素(pivot),假设每次都选择索引为0的元素为轴点元素。
  2. 利用pivot将数组分割成2个子数组,将小于pivot的元素放在pivot前面(左侧),将大于pivot的元素放在pivot后面(右侧),等于pivot的元素放哪边都可以。
  3. 递归对子序列进行前面两步操作,直到不能再分割(子序列中只剩下1个元素)。

快速排序的本质:逐渐将每一个元素都转换成轴点元素。

在这里插入图片描述

动图演示

在这里插入图片描述

代码实现

  1. package com.morris.data.struct.sort.cmp;
  2. import com.morris.data.struct.sort.AbstractSort;
  3. /** * 快速排序 */
  4. public class QuickSort<E extends Comparable> extends AbstractSort<E> {
  5. @Override
  6. protected void sort() {
  7. sort(0, array.length);
  8. }
  9. private void sort(int begin, int end) {
  10. if(end - begin < 2) {
  11. return;
  12. }
  13. int pivotIndex = pivotIndex(begin, end);
  14. sort(begin, pivotIndex);
  15. sort(pivotIndex + 1, end);
  16. }
  17. /** * 返回轴点元素的真正索引 * @param begin * @param end * @return */
  18. private int pivotIndex(int begin, int end) {
  19. // 随机选择一个元素跟begin位置进行交换,为了降低最好时间复杂度
  20. swap(begin, begin + (int)(Math.random() * (end - begin)));
  21. E pivot = array[begin];
  22. end--;
  23. while (begin < end) {
  24. while (begin < end) {
  25. // 从右向左扫描
  26. if(cmp(array[end], pivot) < 0) {
  27. array[begin++] = array[end];
  28. break;
  29. } else {
  30. end--;
  31. }
  32. }
  33. while (begin < end) {
  34. // 从左向右扫描
  35. if(cmp(array[begin], pivot) > 0) {
  36. array[end--] = array[begin];
  37. break;
  38. } else {
  39. begin++;
  40. }
  41. }
  42. }
  43. array[begin] = pivot; // begin==end
  44. return begin;
  45. }
  46. }

在轴点左右元素数量比较均匀的情况下,同时也是最好的情况,所以最好时间复杂度和平均时间复杂度均为O(nlogn)。

如果轴点左右元素数量极度不均匀就会出现最坏情况,所以最坏时间复杂度为O(n^2)。

为了降低最坏情况的出现概率,一般采取的做法是:随机选择轴点元素。

由于递归调用的缘故,所以空间复杂度为O(logn)。

对相等元素的处理

当代码中下面两处的比较为<或>时,快速排序对相等元素的处理过程如下:

  1. ...
  2. // 从右向左扫描
  3. if(cmp(array[end], pivot) < 0) {
  4. ...
  5. ...
  6. // 从左向右扫描
  7. if(cmp(array[begin], pivot) > 0) {
  8. ...

在这里插入图片描述

如果数组中的所有元素都与轴点元素相等,利用目前的算法实现,轴点元素可以将数组分割成2个均匀的子序列。

当代码中下面两处的比较为<=或>=时,快速排序对相等元素的处理过程如下:

  1. ...
  2. // 从右向左扫描
  3. if(cmp(array[end], pivot) <= 0) {
  4. ...
  5. ...
  6. // 从左向右扫描
  7. if(cmp(array[begin], pivot) >= 0) {
  8. ...

在这里插入图片描述
根据轴点元素分割出来的子数组极度不均匀,会导致出现最坏时间复杂度O(n^2)。

更多精彩内容关注本人公众号:架构师升级之路
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,260人围观)

还没有评论,来说两句吧...

相关阅读

    相关 排序算法Java实现

    > 之前写了JavaScript实现的排序算法,因为社会的压迫233333,Java可能也得写写,所以就将这个放在这里来了,算法介绍看之前JavaScript那一篇播客吧,这里

    相关 排序算法快速排序Java实现

    快速排序是一种交换排序,这种排序的思想是把数组通过不断的递归,把数组中的数据分成两部分,前半部分小于某一个数,后半部分大于这个数,接着再对这两部分分别使用这种思想进行交换排序。