今天来手写一下三大经典排序算法吧,这个是非常基础的算法了。虽说基础吧,但是如果长时间不写,一下子未必能很熟练的写出来~ 把这三个放在一起是因为他们的时间复杂度都是O(NlogN),是效率比较高的排序算法。
(随机)快速排序
首先是快排,左神讲快排给我留下的印象挺深的,感觉比较好记。大意就是,在数组的左边划分一个less区(默认-1),右边划分一个more区(初始状态是包含最后一个元素)。
首先取随机一个位置(当然不包括最后一个位置)上的值跟最后一个位置上面的交换,避免遇到基本有序的数组导致快排退化成冒泡排序。以最后一个数作为pivot,遍历数组,遇到比他小的就和arr[++less]交换,再往前走;遇到相等的直接向前走;遇到比他大的,与arr[–more]交换,不往前走,继续循环。
具体看下面代码:
public static void quickSort(int[] nums, int l, int r){
if (nums==null || l>=r)
return;
int pos = partition(nums, l, r);
quickSort(nums, l, pos-1);
quickSort(nums, pos+1, r);
}
private static int partition(int[] nums, int l, int r){
int random_pos = l + (int)(Math.random() * (r-l+1));
swap(nums, random_pos, l);
int tmp = nums[l];
while (l != r){
while (l<r && nums[r]>=tmp)
r--;
if (l<r)
nums[l] = nums[r];
while (l<r && nums[l]<=tmp)
l++;
if (l<r)
nums[r] = nums[l];
}
// l == r
nums[l] = tmp;
return l;
}
private static void swap(int[] arr, int l, int r){
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
-
时间复杂度:
partition的过程时间复杂度是O(N), 最好的情况下每次都把数组从中间分开,进行logN次划分(指的是整体的时间复杂度为O(N)的划分)即可达到终止条件返回,时间复杂度为O(NlogN)。
最差的情况下,数组基本有序,每次只能确定最后一个数的位置,退化成冒泡排序,划分N次,时间复杂度为O(N^2)。
平均时间复杂度为O(NlogN)。 -
空间复杂度:
递归调用需要额外的栈空间,空间复杂度等于递归栈的深度也就是递归的次数。最好情