快速排序算法详解与其他排序算法的比较
快速排序
属于原地排序,与自顶向下归并类似的是,也是先进行大数组的排序,然后递归到小数组,在进行排序时,先选定一个元素为切分元素,按大小将其他元素放到左右两侧即可
步骤:
- 确定切分元素,定义两个位于数组首尾的左右扫描指针
- 左指针遇到大于等于切分元素的元素时,停止移动;右指针遇到小于等于切分元素的元素时,停止移动;
- 当左右指针都停止时,交换左右指针所在元素
- 左右指针继续移动,交换,直到两者重合
- 重合后,重合位置元素与切分元素交换位置
- 再对切分元素左侧和右侧的元素分别进行快速排序,依次循环进行
动画演示: P为切分元素 L为左标记 R为有标记
package Sort; import edu.princeton.cs.algs4.StdRandom; import static Sort.SortExample.*; import static edu.princeton.cs.algs4.StdRandom.uniform; import static edu.princeton.cs.algs4.StdRandom.validateNotNull; public class QuickSort { // 主函数 public static void sort(Comparable[] a){ StdRandom.shuffle(a); // 调用了algs4.jar 中的源代码 sort(a, 0, a.length-1); if(!isSorted(a)) System.out.println("快速排序失败"); } // 为algs4.jar 中的源代码 // 将数组再次打乱 减少了对输入的依赖 public static void shuffle(Object[] a) { validateNotNull(a); // 判断数组是否为空 int n = a.length; for (int i = 0; i < n; i++) { int r = i + uniform(n-i); // between i and n-1 // 交换位置操作 Object temp = a[i]; a[i] = a[r]; a[r] = temp; } } // 为 algs4.jar 中的源代码 private static void validateNotNull(Object x) { if (x == null) { throw new IllegalArgumentException("argument is null"); } } private 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); } // 将数组分为 a[lo...,i-1] a[i] a[i+1..hi] private static int partition(Comparable[] a, int lo, int hi){ int i = lo, j = hi+1; // 定义左右扫描指针 Comparable v = a[lo]; // 定义切分元素 // 扫描左右,检查扫描是否结束并交换元素 while (true){ while (less(a[++i], v)) // 左标记不断向右移动,直到有元素>=切分元素 if(i == hi) // 当左标记到达最右端,跳出循环 break; while (less(v, a[--j])) // 右标记不断向左移动,直到有元素<=切分元素 if(j == lo) // 当右标记到达最左端,跳出循环 break; if(i >= j) // 当左标记与右标记重合,跳出大循环 break; exch(a, i, j); // 当左右标记满足条件停止移动时,交换标记所在的元素 } exch(a, lo, j); // 将 v= a[j] 放入正确的位置 return j; // 返回切分元素索引,此时a[j] 左右两侧完成排序 } }
特点:
- 快速排序如同名字一样,在大多数情况下,具有良好的性能优势
- 大多数编程语言的数组排序内置函数都采用快速排序实现
注意点:
- 当有元素值与切分元素重复时,需要防止循环意外中断
- 保持随机性,不依赖输入,尽量将切分元素也进行随机化
时间复杂度:
N
l
g
N
NlgN
NlgN
四种排序算法的比较
数据来源:algo4 官方提供的 algo4-data.zip 数据包
进行1k数据量的比较:
选择排序,1000个数据,执行时间为:0.0115291 s 插入排序,1000个数据,执行时间为:0.0105386 s 希尔排序,1000个数据,执行时间为:0.0016667 s 自顶向下归并排序,1000个数据,执行时间为:0.0017786 s 自底向上归并排序,1000个数据,执行时间为:6.685E-4 s 快速排序,1000个数据,执行时间为:0.0027377 s
进行32k数据量的比较:
选择排序,32000个数据,执行时间为:4.200542 s 插入排序,32000个数据,执行时间为:2.5466117 s 希尔排序,32000个数据,执行时间为:0.0212745 s 自顶向下归并排序,32000个数据,执行时间为:0.0246908 s 自底向上归并排序,32000个数据,执行时间为:0.0140204 s 快速排序,32000个数据,执行时间为:0.021905 s
其他有关排序算法的文章:
选择排序,插入排序,希尔排序的详解与比较
本文作者:清澈的澈
本文链接:https://www.cnblogs.com/lmc7/p/17531392.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步