归并排序
归并排序需要用到递归,把一个数组分为若干个小数组,一次砍一半,然后再砍左边一半的一半,再砍右边一半的一半,依次砍下去,然后做排序。然后放到一个辅助数组里面合并排序再复制回原来的数组。
public class MergeSort {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
mergeSort(arr, 0, arr.length - 1);
}
public static void mergeSort(int[] arr, int L, int R) {
if (L == R) {
return;
}
int mid = L + ((R - L) >> 1);// 取中点
mergeSort(arr, L, mid);
mergeSort(arr, mid + 1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int mid, int R) {
int[] help = new int[R - L + 1];
int i = 0, p1 = L, p2 = mid + 1;
while (p1 <= mid && p2 <= R) {
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid) {
help[i++] = arr[p1++];
}
while (p2 <= R) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
}
public static void main(String[] args) {
int[] arr = { 6, 3, 2, 1, 5, 0, 9, 8 };
mergeSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
快排
经典快排,首先把最后一个值X作为划分值,然后把小于X的值全部放在左边,大于X的值全部放在右边,然后依次对左右两部分再次进行同样的操作(左半部分用等于X值的前一个坐标的数作为基准),直到排好序。
随机快排,随机选一个数,然后用这个数来进行上述操作,最坏情况下快排时间复杂度为O(N^2)。随机快排打乱了数据状况,平均时间复杂度为O(N*logN)。
改进快排(荷兰国旗问题),第一次取一个值为X,小于X的数放左边,等于X的值放中间,大于X的值放右边。优势在我们一次搞定了N个数,随机快排和经典快排一次都只搞定一个数,改进快排,在经过第一次排序之后,第二次排序,左部分的右边界就是等于X值的第一个数位置-1,右部分的左边界就是等于X值的最后一个数位置+1,中间=X的部分我们不用再管了,优势就在时间复杂的常数项上面。
这里代码给出改进后的随机快排,去掉一行就是改进后的经典快排。
public class QuickSort {
public static void main(String[] args) {
int[] arr = { 4, 6, 3, 7, 8, 2, 1, 5, 9 };
quickSort(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.print(i + " ");
}
}
public static void quickSort(int[] arr, int L, int R) {
if (L < R) {
swap(arr, l + (int) (Math.random() * (r - l + 1)), r); // 加上这一行就是改进后的随机快排
int[] p = partition(arr, L, R);
quickSort(arr, L, p[0] - 1);
quickSort(arr, p[1] + 1, R);
}
}
public static int[] partition(int[] arr, int L, int R) {
int less = L - 1, more = R;
while (L < more) {
if (arr[L] < arr[R]) {
swap(arr, ++less, L++);
} else if (arr[L] > arr[R]) {
swap(arr, --more, L);
} else {
L++;
}
}
swap(arr, more, R);
return new int[] { less + 1, more };
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}