对排序算法总结,考研时本来很熟悉,过段时间很多细节又忘记了,写篇blog总结一下。
O(nlogn)
首先当n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序。
快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
快速排序Quick Sort
Arrays.sort()方法底层就用的快速排序和插入排序,对于元素少的用插入排序,对于元素多的用快速排序。
算法思想
1)选择一个基准元素,通常选择第一个元素
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。
首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(请自己想一想为什么)。哨兵j一步一步地向左挪动(即j–),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。
同样交换 4 与 9.
第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。
第一轮排序就结束了,接下来递归对6左右的数值排序
代码实现
//left和right是想排序的数值下标范围
public void quickSort(int[] arr,int left,int right){
// 如果left不小于right,需要排序的部分只有一个元素,方法返回
if(left >= right){
return;
}
//设置最左边的元素为基准点:pivot
int p = arr[left];
//把要排序的序列中比p大的放到右边,比p小的放到左边,P的下标为i
int i =left;
int j =right;
while(i<j){
//j向左移,找到一个比p小的元素
while(arr[j]>=p && i<j){
j--;
}
//i向右移,找到一个比p大的元素
while(arr[i]<=p && i<j){