Java经典快排思想以及快排的改进讲解

 更新时间:2019年01月04日 08:33:16   作者:sdr_zd  
今天小编就为大家分享一篇关于Java经典快排思想以及快排的改进讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

一.经典快排思想

前提条件:给定一个无序数组arr

  1. 取这个数组最后一个数 num 作为标准,将前面部分的数分为两部分,使得<=num的部分在左边,>num的数在右边;
  2. 然后将最后一个数和>num部分的第一个数进行交换,就使得原本在数组最后位置的num找到了正确的位置,它的左边都是比它小的以及和它一样的数,右边都是比它大的数
  3. 回到1,进行递归或迭代,使得所有的数都找到正确的位

二.通过荷兰国旗问题改进快排

什么是荷兰国旗问题?

已知一个整形数组arr,和一个整数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。

解决思路:

遍历数组

  • 1. 若比num小,当前位置和小于的最后一个位置+1的值交换,并当前位置++;
  • 2. 若比num大,当前位置和大于的第一个位置-1的值交换;
  • 3. 若等于num的值,当前位置++;

附上代码:

public static void NetherlandsFlag(int[] arr, int L, int R, int num) {
 int i = L;
 int p1 = L-1;
 int p2 = R+1;
 //终止条件:当前数的位置在大于区的前一个
 while(i < p2) {
  if(arr[i] < num) {
   //当前数比num小,放左边,i位置上的数和L上的数进行交换,并且i++,L++
   swap(arr, i++, ++p1);
  } else if(arr[i] == num) {
   //当前数和num相等,i++
   i++;
  } else {
   //当前数比num大,放右边,i位置上的数和R上的数进行交换,并且i++,R--
   swap(arr, i, --p2);
  }
 }
}

我们可以发现,荷兰国旗问题和经典快排不同的就只是将<=num改为了< num和=num两部分,借用这个思想使得原来每次只可以让一个数找到正确的位置改进为了每次至少让一个数找到位置。

三.在这基础上将其改为随机快排

随机快排改进的地方只是在选取数的时候,将每次都选取最后位置的数改为选取随机的一个数作为num,这样做的好处是什么呢?

1.选取最后一个数:如果是一个已经排好序的数组,每次找到位置之后,左边是要进行排序的部分,数组长度是原长度-1,它的时间复杂度就是O(N^2);如果每次找到的数都是中间的位置,它的时间复杂度就只有O(logN)

2.然而以随机数作为选取的标准num的时候,因为是随机的,就只能通过数学期望去计算它的时间复杂度,时间复杂度是O(logN)

下面附上最终的快排代码及注释

/*
 * swap(int[] arr, int i, int j);是将arr数组的i和j位置上的数交换的方法
 */
public static void quickSort(int[] arr) {
 // 如果为空或长度为1不需要排序,直接返回
 if(arr == null || arr.length < 2)
  return;
 else
  quickSort(arr, 0, arr.length - 1);
}
// 递归排序
public static void quickSort(int[] arr, int L, int R) {
 if(L < R) {
  /*
   * 随机快排的随机就在这
   * 是随机选取了一个数,和 R 进行了交换,然后使用这个数作为num,
   * 所以每次选取的num是随机的,
   * 在计算时间复杂度时,是没有最优最差情况的
   * 而是通过一个长期的数学期望计算的,结果是O(N*logN)
   */
  swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
  int[] border = partition(arr, L, R);
  // 小于区和大于区进行递归
  quickSort(arr, L, border[0] - 1);
  quickSort(arr, border[1] + 1, R);
 }
}
// 将给定数组划分为小于区、等于区和大于区
public static int[] partition(int[] arr, int L, int R) {
 int num = arr[R];
 int less = L - 1;
 int more = R + 1;
 int curr = L;
 // 分为小于区等于区和大于区
 while(curr < more) {
  if(arr[curr] < num) {
   swap(arr, curr++, ++less);
  } else if(arr[curr] > num) {
   swap(arr, curr, --more);
  } else {
   curr++;
  }
 }
 //返回等于区的左右边界的下标,通过下标确定小于区和大于区递归时的参数
 return new int[] {less + 1, more - 1};
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • Spring DevTools的介绍

    Spring DevTools的介绍

    今天小编就为大家分享一篇关于Spring DevTools的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java中API的使用方法详情

    Java中API的使用方法详情

    这篇文章主要介绍了Java中API的使用方法详情,指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用,需要的朋友可以参考下
    2022-04-04
  • Java开发常用类库之Hutool详解

    Java开发常用类库之Hutool详解

    这篇文章主要介绍了Java开发常用类库之Hutool,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 高效的java版排列组合算法

    高效的java版排列组合算法

    这篇文章主要为大家详细介绍了高效的java版排列组合算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Java注释代码执行方法解析

    Java注释代码执行方法解析

    这篇文章主要介绍了Java注释代码执行方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • 用JAVA实现单链表,检测字符串是否是回文串

    用JAVA实现单链表,检测字符串是否是回文串

    这篇文章主要介绍了使用JAVA实现单链表,检测字符串是否是回文串,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-11-11
  • springboot如何配置Filter过滤器

    springboot如何配置Filter过滤器

    这篇文章主要介绍了springboot如何配置Filter过滤器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • java 自定义类比较器代码

    java 自定义类比较器代码

    这篇文章主要介绍了java 自定义类比较器代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • java实现简易聊天功能

    java实现简易聊天功能

    这篇文章主要为大家详细介绍了java实现简易聊天功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • @Transaction,@Async在同一个类中注解失效的原因分析及解决

    @Transaction,@Async在同一个类中注解失效的原因分析及解决

    这篇文章主要介绍了@Transaction,@Async在同一个类中注解失效的原因分析及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12

最新评论