/**
* 归并排序:
* 把数组分成两部分。每两部分再分成两部分排序,递归。
* 一直分成每部分只有一个元素。
* 再合并。就变成整体有序了。
*
*
* 时间复杂度:O(nlogn)
* 空间复杂度:O(N),归并排序需要一个与原数组相同长度的数组做辅助来排序
* 稳定性:归并排序是稳定的排序算法,temp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
* 这行代码可以保证当左右两部分的值相等的时候,先复制左边的值,这样可以保证值相等的时候两个元素的相对位置不变。
*
* @param arr
*/
public static void guibingSort(int[] arr) {
sort(arr, 0, arr.length-1);
}
public static void sort(int[] arr, int left, int right){
if(left == right){
return;
}
int mid = left + ((right - left) >> 1);
sort(arr,left,mid);
sort(arr,mid+1,right);
merge(arr,left,mid,right);
}
/**
* 将两个分离开数组合并
* @param arr
* @param left
* @param mid
* @param right
*/
public static void merge(int[] arr, int left, int mid, int right) {
int[] tmp = new int[right - left + 1];
int i = 0;
int p1 = left;
int p2 = mid + 1;
// 比较左右两边的数据,小的放在tmp里面
while (p1 <= mid && p2 <= right) {
if (arr[p1] < arr[p2]) {
tmp[i++] = arr[p1++];
} else {
tmp[i++] = arr[p2++];
}
// 人家的写法,也就是用了一个三目运算
// tmp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 循环结束后。吧另外一个剩下的全部插入到临时数组后面
while (p1 <= mid) {
tmp[i++] = arr[p1++];
}
while (p2 <= right) {
tmp[i++] = arr[p2++];
}
// 把合并好的数组放回原来的数组
for (int j = 0; j < tmp.length; j++) {
arr[left + j] = tmp[j];
}
}
排序方法 |
平均情况 |
最好情况 |
最坏情况 |
辅助空间 |
稳定性 |
冒泡排序 |
N2 |
n |
N2 |
1 |
稳定 |
选择排序 |
N2 |
N2 |
N2 |
1 |
不稳定 |
插入排序 |
N2 |
n |
N2 |
1 |
稳定 |
希尔排序 |
N*logn~n2 |
N1.3 |
N2 |
1 |
不稳定 |
堆排序 |
N*logn |
N*logn |
N2 |
1 |
不稳定 |
归并排序 |
N*logn |
N*logn |
N*logn |
N |
稳定 |
快速排序 |
N*logn |
N*logn |
N2 |
1 |
不稳定 |