快速排序(Quick Sort)

一、基本思想

快速排序是一种分治算法核心思想是:

🌷选定一个基准值(pivot):从数组中选择一个元素作为基准。

🌱分区(Partition):将数组分为两部分,使得左边部分的元素均 ≤ 基准值,右边部分的元素均 ≥ 基准值。

🪴递归排序:对左右两部分递归执行上述过程,直到子数组长度为1或0(已有序)。

二、关键步骤

以升序排序为例:

1.选择基准值:通常选第一个元素、最后一个元素或随机元素(本文以最后一个元素为例)。

分区操作:

2.初始化两个指针:i(指向小于基准的区域的末尾)、j(遍历数组)。

遍历数组,若当前元素 ≤ 基准值,则将其与i+1位置的元素交换,并移动i。

最后将基准值放到i+1的位置,此时基准值的位置已确定。

3.递归排序左右子数组。

三、性能分析

🧀时间复杂度
最优/平均情况:O(n log n),每次分区均匀划分。

最坏情况:O(n²),当数组已有序或逆序时,每次分区极度不平衡(可通过随机选基准避免)。

🍙空间复杂度
递归调用栈的深度:最优O(log n),最坏O(n)。

🍗稳定性
不稳定:分区过程中可能改变相同元素的相对顺序(如交换时跳过相同值)

四、示例代码

C/C++

int partition(int arr[], int low, int high) {
    int pivot = arr[high]; // 选最后一个元素作为基准
    int i = low - 1;       // i 指向小于基准的区域的末尾

    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(arr[i], arr[j]); // 交换到左边
        }
    }
    swap(arr[i + 1], arr[high]); // 基准归位
    return i + 1; // 返回基准位置
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1); // 递归左半部分
        quickSort(arr, pi + 1, high); // 递归右半部分
    }
}

Python

def partition(arr, low, high):
    pivot = arr[high]  # 选最后一个元素作为基准
    i = low - 1        # i 指向小于基准的区域的末尾

    for j in range(low, high):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]  # 交换到左边
    arr[i + 1], arr[high] = arr[high], arr[i + 1]  # 基准归位
    return i + 1  # 返回基准位置

def quick_sort(arr, low, high):
    if low < high:
        pi = partition(arr, low, high)
        quick_sort(arr, low, pi - 1)  # 递归左半部分
        quick_sort(arr, pi + 1, high)  # 递归右半部分

 Java

int partition(int[] arr, int low, int high) {
    int pivot = arr[high]; // 选最后一个元素作为基准
    int i = low - 1;       // i 指向小于基准的区域的末尾

    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot) {
            i++;
            // 交换 arr[i] 和 arr[j]
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    // 基准归位
    int temp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = temp;

    return i + 1; // 返回基准位置
}

void quickSort(int[] arr, int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1); // 递归左半部分
        quickSort(arr, pi + 1, high); // 递归右半部分
    }
}

五、典型例题

【问题描述】输入一组数据,以0作为输入的结束,分别采用冒泡排序、选择排序、快速排序的方法,对其进行从小到大的排序,给出排序后的结果。

【输入形式】一组数据,以0作为输入的结束

【输出形式】三种排序后的结果

【样例输入】

9 8 4 5 7 2 10 6 0
【样例输出】

2 4 5 6 7 8 9 10

2 4 5 6 7 8 9 10

2 4 5 6 7 8 9 10

#include<iostream>
using namespace std;

// 输出数组函数
void output(int a[], int n)
{
    for (int i = 0; i < n; i++)
        cout << a[i] << ' ';  // 输出数组元素,用空格分隔
    cout << endl;  // 换行
}

// 冒泡排序
void bubblesort(int a[], int n)
{
    for (int i = 0; i < n - 1; i++)  // 外层循环控制轮数
    {
        bool flag = false;  // 标记本轮是否发生交换
        for (int j = 0; j < n - 1 - i; j++)  // 内层循环比较相邻元素
        {
            if (a[j] > a[j + 1])  // 如果前一个元素大于后一个元素
            {
                // 交换两个元素
                int t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
                flag = true;  // 标记发生交换
            }
        }
        if (flag == false)  // 如果本轮没有发生交换,说明数组已经有序
            return;
    }
}

// 选择排序
void selectsort(int a[], int n)
{
    for (int i = 0; i < n - 1; i++)  // 外层循环控制当前位置
    {
        int k = i;  // 假设当前位置是最小值的位置
        for (int j = i + 1; j < n; j++)  // 内层循环寻找最小值的位置
        {
            if (a[j] < a[k])  // 如果找到更小的元素
                k = j;  // 更新最小值的位置
        }
        if (k != i)  // 如果最小值不在当前位置
        {
            // 交换最小值到当前位置
            int x = a[i];
            a[i] = a[k];
            a[k] = x;
        }
    }
}

// 快速排序的分区函数
int Part(int a[], int low, int high)
{
    int p = a[low];  // 选择第一个元素作为基准值
    while (low < high)  // 循环直到low和high相遇
    {
        while (low < high && a[high] >= p)  // 从右向左找小于基准值的元素
            --high;
        a[low] = a[high];  // 将小于基准值的元素放到左边
        while (low < high && a[low] <= p)  // 从左向右找大于基准值的元素
            ++low;
        a[high] = a[low];  // 将大于基准值的元素放到右边
    }
    a[low] = p;  // 将基准值放到正确的位置
    return low;  // 返回基准值的位置
}

// 快速排序
void fastsort(int a[], int low, int high)
{
    if (low < high)  // 如果子数组长度大于1
    {
        int p = Part(a, low, high);  // 分区并获取基准值的位置
        fastsort(a, low, p - 1);  // 递归排序左半部分
        fastsort(a, p + 1, high);  // 递归排序右半部分
    }
}

int main()
{
    int a[100];  // 定义数组存储输入数据
    int n = 0;  // 记录数组长度
    for (int i = 0;; i++)  // 循环读取输入
    {
        int x;
        cin >> x;  // 读取输入的数字
        if (x == 0)  // 如果输入为0,结束输入
            break;
        a[i] = x;  // 将数字存入数组
        n++;  // 数组长度加1
    }
    // 冒泡排序并输出结果
    bubblesort(a, n);
    output(a, n);
    // 选择排序并输出结果
    selectsort(a, n);
    output(a, n);
    // 快速排序并输出结果
    fastsort(a, 0, n - 1);
    output(a, n);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小瑾比个耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值