📜  快速排序与合并排序(1)

📅  最后修改于: 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)的排序算法,它们虽然实现方式不同,但都是基于分治算法思想。在实际应用中,我们需要根据实际情况选择适合的排序算法。