这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记。 1、pdqsort 是 Pattern-defeating quicksort 的缩写,是一种新型的排序算法,将随机快速排序的快速平均情况与堆排序的最坏情况快速组合在一起,同时在具有特定模式的输入上实现了线性时间。 2、快速排序(quicksort): 主要采用了分治的思想,具体的过程是将一个 array 通过选定一个 pivot(锚点)分成不同的 sub-arrays,选定 pivot 后,使得这个 array 中位于 pivot 左边的元素都小于 pivot,位于 pivot 右边的元素都大于 pivot。由此,pivot 两边构成了两个 sub-arrays,然后对这些 sub-arrays 进行相同的操作(选定 pivot 然后切分)。当某个 sub-array 只有一个元素时,其本身有序,此时便可以退出循环。如此反复,最后得到整体的有序。
- 选择一个 pivot
- partition: 使用 pivot 对 array 进行划分
/**
- 快速排序法基本思想:首先从待排序列中选定一个枢纽关键字,通过关键字与枢纽的比较将待排序的序列划分成位于枢纽前后的两个子序列,其中枢纽之前的子序列的所有关键字都不大于枢纽,枢纽之后的子序列的所有关键字都不小于枢纽。此时枢纽已到位,再按同样方法对这两个子序列分别递归进行快速排序,最终使得整个序列有序。
- @author Remoa
*/ public class QuickSort implements AlgorithmSort { @Override public void startAlgorithm(List list) { QuickSortVO quickSortVO = new QuickSortVO(); quickSortVO.setList(list); quickSortVO.setPivotloca(0); quicksort(quickSortVO, 0, list.size() - 1); }
/**
* 对序列进行划分
* @param quickSortVO quickSortVO实体
* @param low 位标low指向待排记录的第一个记录
* @param high 位标high指向最后一个记录
* @return QuickSortVO实体
*/
public QuickSortVO partition(QuickSortVO quickSortVO, int low, int high){
Integer pivlot = quickSortVO.getList().get(low);
while(low < high){
while(low < high && quickSortVO.getList().get(high).intValue() >= pivlot.intValue()){
high--;
}
quickSortVO.getList().set(low, quickSortVO.getList().get(high).intValue());
while(low < high && quickSortVO.getList().get(low).intValue() <= pivlot.intValue()){
low++;
}
quickSortVO.getList().set(high, quickSortVO.getList().get(low).intValue());
}
quickSortVO.getList().set(low, pivlot.intValue());
quickSortVO.setPivotloca(low);
return quickSortVO;
}
/**
* 快速排序算法
* @param quickSortVO quickSortVO实体
* @param s 位标s指向待排记录的第一个记录
* @param t 位标t指向最后一个记录
* @return QuickSortVO实体
*/
public QuickSortVO quicksort(QuickSortVO quickSortVO, int s, int t){
if(s < t){
quickSortVO = partition(quickSortVO, s, t);
int temp = quickSortVO.getPivotloca();
quickSortVO = quicksort(quickSortVO, s, temp - 1);
quickSortVO = quicksort(quickSortVO, temp + 1, t);
}
return quickSortVO;
}
}
/**
- QuickSortVO实体,封装了待排序列和枢纽位置
- @author Remoa
*/ class QuickSortVO{ private List list; private int pivotloca;//枢纽位置 public List getList() { return list; } public void setList(List list) { this.list = list; } public int getPivotloca() { return pivotloca; } public void setPivotloca(int pivotloca) { this.pivotloca = pivotloca; }
}
- 短序列情况,对于长度在 [0, MAX_INSERTION] 的输入,使用 insertion sort (插入排序)来进行排序后直接返回,这里的 MAX_INSERTION 我们在 Go 语言下的性能测试,选定为 24。
- 最坏情况,如果发现改进的 quicksort 效果不佳(limit == 0),则后续排序都使用 heap sort 来保证最坏情况时间复杂度为 O(n*logn)。