排序就是将一组对象按照某种逻辑重新排列的过程。

初级排序算法

选择排序

不断重复找到最小的元素,移到相应位置。{0-N} = {0, 1, 2,..N}, {n} = swap( nums[n], min{ nums[n~nums.length] } )

1
2
3
4
5
6
7
let nums = [1,3,5,2,4];
for(let i =0; i< nums.length; i++) {
for(let j = i; j < nums.length; j++) {
minNum = min(minNum, nums[j]);
}
swap(minNum, nums[i]);
}

有 N 次交换和N+(N-1)+..+2+1~N^2/2次比较

插入排序

每次将一个数插入有序数组的适当位置。{0-N} = {0, 1, 2,..N},{n} = { nums[0~n]}.swap( less(nums[n], nums[n-1]) )

1
2
3
4
5
6
7
for(let i=0;i<nums.length; i++) {
for(let j = i; j >0; j--){
if(num[j] < nums[j-1]) {
swap(nums[j], nums[j-1]);
}
}
}

插入排序所需的时间与输入的元素的初始顺序有关,最坏情况下需要N^2/2次比较和N^2/2次交换,最好需要N-1次比较和0次交换

归并排序

要将一个数组排序,可以递归地将它分成两半分别排序,然后在合并起来。{0-N} = merge( {0-N/2}, {N/2-N} );
merge(n) = { min( {0-n/2}, {n/2-n} ) }。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function sort(nums, lo, hi) {
let mid = (lo + hi ) / 2;
sort(nums, lo, mid);
sort(nums, mid+1, hi);
merge(nums,lo, mid, hi);
}
function merge(nums, low, mid, high) {
let i = lo, j = mid +1;
for(let k = lo; k <= high, k++) {
aux[k] = nums[k];
}
for(let k =lo; k<=high;k++) {
if(i>mid) a[k] = aux[j++];
else if(j > hi) a[k] = aux[i++];
else if(less(aux[j], aux[k])) a[k] = aux[j++];
else a[k] = aux[i++];
}
}

时间复杂度NlgN,空间复杂度N,比初级算法较优

快速排序

当两个子数组有序时,就完成了排序。{0-N} = {0-K} + {K-N};partition(n) = swap( n1<k, k<n2 ),k = nums[lo]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function sort(nums, lo, hi) {
let j = partition(nums,lo, hi);
sort(nums, lo, j-1);
sort(nums, j+1, hi);
}
function partition(nums, lo ,hi) {
let i = lo, j = hi, k = nums[lo];
while(true) {
while(a[++i] < k) if(i = hi) break;
while(a[++j] > k) if(j = lo) break;
if(i>j) break;
swap(nums[i], nums[j]);
}
swap(nums[lo], nums[j]);
return j;
}

时间复杂度NlgN,空间复杂度lgN