快速排序
- 算法思想
- partition函数
- 函数签名
- 变量定义
- 选择基准元素
- 初始化指针
- 遍历并分区
- 最终交换
- 返回基准元素的位置
- 完整函数
- QuickSort函数
- 函数定义
- 终止条件
- 划分(partition)
- 递归调用
- 完整函数
算法思想
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;
}