快速排序!

算法思想

partition函数

partition函数是快速排序算法中的一个关键部分。它的作用是将数组分区,并返回基准元素(pivot)的位置,使得基准元素左边的元素都小于它,右边的所有元素都大于或等于它。

函数签名

int partition(int a[], int l, int r)
a[] : 要进行分区的数组
l : 当前分区的起始索引
r : 当前分区的结束索引

变量定义

int i, j, pivot;
i 和 j : 用于遍历和分区数组的索引
pivot: 存储选取的基准元素的值

选择基准元素

int idx = l + rand() % (r - l + 1); pivot = a[idx]; Swap(&a[l], &a[idx]);
idx: 随机选择基准元素的索引,范围在[l,r]之间
快速排序」在众多排序算法中效率较高,平均时间复杂度为 O(nlogn)。但当完全有序时,最坏时间复杂度达到最坏情况 O(n^2)。
所以每次在选择基准数的时候,我们可以尝试用随机的方式选取,这就是「随机快速排序」。
pivot: 基准元素的值,即a[idx]
Swap(&a[l], &a[idx]): 将基准元素与当前分区的第一个元素交换,以便后续操作方便

初始化指针

i = j = l + 1;
i 和 j 都初始化为l+1,即基准元素之后的第一个元素

遍历并分区
while (i <= r)
{
    if (a[i] < pivox)
    {
        Swap(&a[i], &a[j]);
        j++;
    }
    i++;
}

while(i <= r): 遍历当前分区的所有元素
如果a[i]小于基准元素pivot:
将a[i]和a[j]交换,得到a[j]位于较小元素的区域
增加j,以扩展较小元素的区域

最终交换

Swap(&a[l], &a[j - 1]);
将基准元素a[l]与a[j - 1]交换,将基准元素放到正确的位置

返回基准元素的位置

return j - 1;

完整函数
int partition(int a[], int l, int r)
{
    int i, j, pivot;
    int idx = l + rand() % (r - l + 1);
    pivot = a[idx];
    Swap(&a[l], &a[idx]);
    i = j = l + 1;
    while (i <= r)
    {
        if (a[i] < pivot)
        {
            Swap(&a[i], &a[j]);
            j++;
        }
        i++;
    }
    Swap(&a[l], &a[j - 1]);
    return j - 1;
}

QuickSort函数

QuickSort是快速排序算法的一个实现。快速排序是一种高效的排序算法,通常用于对大规模数据进行排序。它采用分而治之的策略,通过递归地对数组进行划分和排序,最终实现整个数组的有序排列。

函数定义

void QuickSort(int a[], int l, int r)
a[]: 待排序的数组
l: 数组的左边界索引(起始位置)
r: 数组的右边界索引(结束位置)

终止条件

if (l < r)
当l小于r时,表示当前子数组至少有两个元素需要排序,如果l不小于r,说明子数组已经有序或只有一个元素,不需要进一步操作

划分(partition)

int mid = partition(a, l, r);
partition函数的作用时将数组a的某一部分划分为两部分,并返回一个分界点mid,使得该点右边的元素都小于等于该点上的元素,右边的元素都大于等于该点上的元素。

递归调用

QuickSort(a, l, mid - 1);
QuickSort(a, mid + 1, r);
在partition之后,数组被分成了两个子数组:

  • 左子数组:范围是从l到mid-1
  • 右子数组:范围是从mid+1到r
    QuickSort递归地对这两个子数组分别进行排序,知道所有子数组都是有序的

完整函数

#include <stdio.h>
#include <stdlib.h>
#define maxn 1000001
int a[maxn];

void Input(int n, int *a) // 从键盘输出数据到a数组中
{
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
}

void Output(int n, int *a) // 把数组a的内容依次输出
{
    for (int i = 0; i < n; i++)
    {
        if (i != 0)
            printf(" ");
        printf("%d", a[i]);
    }
    puts("");
}

void Swap (int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int partition(int a[], int l, int r)
{
    int i, j, pivot;
    int idx = l + rand() % (r - l + 1);
    pivot = a[idx];
    Swap(&a[l], &a[idx]);
    i = j = l + 1;
    while (i <= r)
    {
        if (a[i] < pivox)
        {
            Swap(&a[i], &a[j]);
            j++;
        }
        i++;
    }
    Swap(&a[l], &a[j - 1]);
    return j - 1;
}

void QuickSort(int a[], int l, int r)
{
    if (l < r)
    {
        int mid = partition(a, l, r);
        QuickSort(a, l, mid - 1);
        QuickSort(a, mid + 1, r);
    }
}
int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        Input(n, a);
        QuickSort(a, 0, n - 1);
        Output(n, a);
    }
    return 0;
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值