📅  最后修改于: 2023-12-03 15:09:54.367000             🧑  作者: Mango
快速排序和合并排序都是排序算法中比较经典的两种,它们都是基于分治算法思想。快速排序通过选择一个基准元素,将待排序序列划分成两个子序列,使得左子序列中的元素都小于基准元素,右子序列中的元素都大于基准元素,然后递归地对左子序列和右子序列进行排序。合并排序则是将待排序序列递归地划分成两个子序列,然后对这两个子序列进行排序,最后将排序后的子序列合并成一个有序序列。
在待排序序列中选择一个基准元素,将序列划分成两个子序列。然后递归地对左子序列和右子序列进行排序。
void quick_sort(int arr[], int start, int end) {
if (start >= end) {
return;
}
int pivot = arr[start];
int left = start, right = end;
while (left < right) {
while (left < right && arr[right] >= pivot) {
right--;
}
if (left < right) {
arr[left] = arr[right];
left++;
}
while (left < right && arr[left] < pivot) {
left++;
}
if (left < right) {
arr[right] = arr[left];
right--;
}
}
arr[left] = pivot;
quick_sort(arr, start, left - 1);
quick_sort(arr, left + 1, end);
}
时间复杂度:O(nlogn)。最好情况下,每次选择的基准元素都是序列中的中位数,则时间复杂度为O(nlogn);最坏情况下,每次选择的基准元素都不合适,则时间复杂度为O(n^2)。平均时间复杂度为O(nlogn)。
空间复杂度:O(logn),需要递归调用栈。
在待排序序列中递归地将序列划分成两个子序列,然后对这两个子序列进行排序,最后将排序后的子序列合并成一个有序序列。
void merge(int arr[], int start, int mid, int end) {
int len1 = mid - start + 1;
int len2 = end - mid;
int L[len1], R[len2];
for (int i = 0; i < len1; i++) {
L[i] = arr[start + i];
}
for (int j = 0; j < len2; j++) {
R[j] = arr[mid + 1 + j];
}
int i = 0, j = 0, k = start;
while (i < len1 && j < len2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < len1) {
arr[k] = L[i];
i++;
k++;
}
while (j < len2) {
arr[k] = R[j];
j++;
k++;
}
}
void merge_sort(int arr[], int start, int end) {
if (start >= end) {
return;
}
int mid = (start + end) / 2;
merge_sort(arr, start, mid);
merge_sort(arr, mid + 1, end);
merge(arr, start, mid, end);
}
时间复杂度:O(nlogn)。因为每次合并两个子序列的时间复杂度为O(n),而递归划分序列的次数为logn,所以总的时间复杂度为O(nlogn)。
空间复杂度:O(n),需要一个辅助数组来合并子序列。
快速排序和合并排序都是时间复杂度为O(nlogn)的排序算法,它们虽然实现方式不同,但都是基于分治算法思想。在实际应用中,我们需要根据实际情况选择适合的排序算法。