排序算法之快速排序
前2段是废话可直接看第3段,coding多年一些常见算法及原理还是记得的,平时习惯了IDE去 “.” 出一些方法,在跳槽面试中让编写算法及优化时也是抓瞎,其实算法原理应该是上动态图片更直观些的,无奈曾经遇到过大神制作的动图没有保存,自己又比较笨拙不会制作,但文章结尾会贴出本人参照较好的文章供大家一起分析。
在此也声明下,本人学习期间会参照一些老师及大神的书籍或博客,个人认为我不懂就要和懂的人学习知识并吸收总结成自己的,这其实没有什么丢人的,所以博客、代码均通过收集资料分析、编写、优化、测试及总结整理后书写博客与大家分享,目的在于自我加深印象,分享及传播知识。希望大家就实际问题相互学习探讨,请勿互掐。
快速排序:采用 三数取中法+分治法+挖坑填数
三数取中法:为提升效率避免分组不合理的情况,比如逆序数组,提前将数组选左中右3个数将数组排序分割,之后再进行分治法排序,图解可参照参考博客[2] 的三数取中法 。
分治法:将数组从中分割开2部分,1变2,2变4,4变8…分割后在进行排序。
挖坑填数:本质是元素交换。先把基准值挖出来,位置留出来为坑1;从后向前找到比基准小的元素挖出来,此位置为坑2,将元素填到坑1中;从前往后找到比基准大的元素挖出来,此位置为坑3,放到刚才挖的坑2中;将基准值填补到坑3中,然后分治递归快排。总结就是挖了三个坑:坑1(基准坑)、坑2、坑3,有了三块土:土1(基准值)、土2、土3,土2填坑1,土3填坑2,土1(基准值)填坑3,图解可参照参考博客[1] 的快速排序。
直接上测试代码:
import java.util.Arrays;
/**
* @Author: Wenx
* @Description: 快速排序
* @Date: Created in 2020/3/6 17:35
* @Modified By:
*/
public class QuickSort<T extends Comparable<T>> implements Sort<T> {
@Override
public void sort(T[] values) {
int size = values.length;
int low = 0;
int high = size - 1;
sort(values, low, high);
}
private void sort(T[] values, int low, int high) {
if (low < high) {
dealPivot(values, low, high);
int pivotIdx = partition(values, low, high);
sort(values, low, pivotIdx - 1);
sort(values, pivotIdx + 1, high);
}
}
private void dealPivot(T[] values, int low, int high) {
int mid = (low + high) / 2;
if (values[low].compareTo(values[mid]) == 1) {
swap(values, low, mid);
}
if (values[low].compareTo(values[high]) == 1) {
swap(values, low, high);
}
if (values[high].compareTo(values[mid]) == -1) {
swap(values, high, mid);
}
swap(values, high - 1, mid);
}
private int partition(T[] values, int low, int high) {
int l = low;
int r = high;
// 挖坑1:保存基准的值
T pivot = values[low];
while (l < r) {
// 挖坑2:从后向前找到比基准小的元素,插入到基准位置坑1中
while (l < r && values[r].compareTo(pivot) > -1) {
r--;
}
values[l] = values[r];
// 挖坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中
while (l < r && values[l].compareTo(pivot) < 1) {
l++;
}
values[r] = values[l];
}
// 基准值填补到坑3中,准备分治递归快排
values[l] = pivot;
return l;
}
private void swap(T[] values, int a, int b) {
T t = values[a];
values[a] = values[b];
values[b] = t;
}
public static void main(String[] args) {
Integer[] values = {1, 5, 4, 3, 2, 6, 7, 8, 9};
Sort<Integer> sort = new QuickSort<>();
long startTime = System.nanoTime();
sort.sort(values);
long endTime = System.nanoTime();
System.out.printf("耗时:%d ns, %s\n", endTime - startTime, Arrays.toString(values));
}
}
留个接口方便后续操作:
/**
* @Author: Wenx
* @Description: 排序接口
* @Date: Created in 2020/3/5 17:15
* @Modified By:
*/
public interface Sort<T extends Comparable<T>> {
void sort(T[] values);
}
总结:重点在于理解原理,使之变为自己的知识,编码可参照众多实现形式,每个人理解及想法均有差异,结合他人及自己想法转化实践就好了~
参考博客:
[1] https://blog.youkuaiyun.com/dp_dp/article/details/80543290
[2] https://blog.youkuaiyun.com/jiangtianjiao/article/details/88929408