归并排序(分治)
递推公式:
merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
终止条件:
p >= r 不用再继续分解
//伪代码
// 归并排序算法, A 是数组,n 表示数组大小
merge_sort(A, n) {
merge_sort_c(A, 0, n-1)
}
// 递归调用函数
merge_sort_c(A, p, r) {
// 递归终止条件
if p >= r then return
// 取 p 到 r 之间的中间位置 q
q = (p+r) / 2
// 分治递归
merge_sort(A, p, q)
merge_sort(A, q+1, r)
// 将 A[p...q] 和 A[q+1...r] 合并为 A[p...r]
merge(A[p...r], A[p...q], A[q+1...r])
}
代码实现
/**
* 归并排序
* 分治的方法、从下治上归并以达到有序、分治使用递归实现
*
* 递推公式
* sort(left,right) = sort(mergeSort(left,middle),mergeSort(middle+1,right))
* 终止条件
* left >= right 不用继续分解
*/
public class MergeSort {
public static int[] temp;
public static void sort(int[] arr) {
temp = new int[arr.length];
mergeSort(arr, 0, arr.length - 1);
}
private static void mergeSort(int[] arr, int left, int right) {
if (left >= right) {
return;
}
int middle = (left + right) / 2;
mergeSort(arr, left, middle);
mergeSort(arr, middle + 1, right);
merge(arr, left, middle, right);
}
private static void merge(int[] arr, int left, int middle, int right) {
int i = left;
int j = middle + 1;
int k = 0;
while (i <= middle && j <= right) {
if (arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
//剩余元素拷贝到数组中
while (i <= left) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
//将临时数据元素复制回原数组
for (i = 0; i < k; i++) {
arr[left + i] = temp[i];
}
}
}
性能分析
是稳定算法吗
是稳定算法
时间复杂度
最好、最坏、平均时间复杂度都是O(nlogn)
空间复杂度
空间复杂度为O(n)
快速排序(分治)
递推公式:
quick_sort(p…r) = quick_sort(p…q-1) + quick_sort(q+1, r)
终止条件:
p >= r
//伪代码
// 快速排序,A 是数组,n 表示数组的大小
quick_sort(A, n) {
quick_sort_c(A, 0, n-1)
}
// 快速排序递归函数,p,r 为下标
quick_sort_c(A, p, r) {
if p >= r then return
q = partition(A, p, r) // 获取分区点
quick_sort(A, p, q-1)
quick_sort(A, q+1, r)
}
代码实现
public static void sort2(int[] arr) {
innerSort2(arr, 0, arr.length - 1);
}
private static void innerSort2(int[] arr, int left, int right) {
if (left >= right) {
return;
}
int partition = partition(arr, left, right);
innerSort2(arr, left, partition - 1);
innerSort2(arr, partition + 1, right);
}
private static int partition(int[] arr, int left, int right) {
int i = left;
int j = right;
int temp = arr[left];
while (i != j) {
if (i < j && arr[i] <= temp) {
i++;
}
if (i < j && arr[j] >= temp) {
j--;
}
if (i < j){
Utils.exchange(arr,i,j);
}
}
arr[left] = arr[i];
arr[i] = temp;
return i;
}
性能分析
是稳定算法吗
不稳定算法
时间复杂度
最好O(nlogn)、最坏O(n²)、平均时间复杂度都是O(nlogn)
空间复杂度
O(1)