RedSenior

导航

快速排序的学习

快速排序

思想:
不同于归并,快速排序的本质是分治,且一直分,分到最小。即通过递归选中间值x将待排序的内容分为左右两个待排序区域。一直递归排序,将左边的都变成小于等于x的,右边的值都大于等于x。一直分分分到最小————即左右只有一个值。

代码如下

#include<iostream>
using namespace std;

const int N = 100010;
int q[N];  // 用于存储待排序的数组

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;  // 递归终止条件:当左边界大于或等于右边界时,停止排序

    int i = l - 1, j = r + 1, x = q[(r + l) / 2];  // i 和 j 为左右指针,x 为基准值(这里选取中间元素)
    
    while (i < j)
    {
        // 在 i 位置向右寻找第一个大于等于基准值的元素
        do i++; while (q[i] < x);

        // 在 j 位置向左寻找第一个小于等于基准值的元素
        do j--; while (q[j] > x);

        if (i < j) swap(q[i], q[j]);  // 如果 i 小于 j,交换这两个元素
    }

    // 对左半部分进行递归排序
    quick_sort(q, l, j);

    // 对右半部分进行递归排序
    quick_sort(q, j + 1, r);
}

int main()
{
    int n;
    cin >> n;  // 输入数组的大小
    for (int i = 0; i < n; i++) cin >> q[i];  // 输入待排序的元素

    // 调用快速排序算法
    quick_sort(q, 0, n - 1);

    // 输出排序后的数组
    for (int i = 0; i < n; i++) cout << q[i] << " ";

    return 0;
}

平均时间复杂度:O(n log n),这是快速排序最常见的情况。
最坏时间复杂度:O(n^2),发生在数组已经有序或者基准元素总是选得不好时。为避免这种情况,通常可以随机选择基准元素或使用三数取中法。
空间复杂度:O(log n),这是由于递归调用栈的空间开销。
举个例子说明:
假设我们有一个数组:[10, 7, 8, 9, 1, 5],我们选择基准值为 8,并执行分区操作:

1.初始状态:[10, 7, 8, 9, 1, 5],选择基准值 8。
2.左指针 i 从左往右扫描,找到 10,右指针 j 从右往左扫描,找到 5。
3.交换 10 和 5,得到:[5, 7, 8, 9, 1, 10]。
4.继续扫描,交换 9 和 7,得到:[5, 7, 8, 9, 1, 10]。
5.继续分区操作直到指针相遇,最后,数组分成 [5, 7, 8] 和 [9, 10],基准值 8 被放到了正确的位置。
然后我们递归地对 [5, 7] 和 [9, 10] 继续排序。

posted on 2024-11-30 21:12  RedLouie  阅读(3)  评论(0编辑  收藏  举报