快速排序算法模板
------ 模板题 AcWing 785. 快速排序
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[(l + r )/2];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
归并排序算法模板
------ 模板题 AcWing 787. 归并排序
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = (l + r )>> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
1. 快速排序算法(Quick Sort)
思考过程:
快速排序的核心思想是 分治法 ,通过选择一个基准值(通常是数组的中间值 或者某个随机位置的值),将数组分成两部分,使得左边部分的元素小于基准值,右边部分的元素大于基准值(比较大小且交换)。然后递归地对子数组进行排序,直到整个数组有序。
具体步骤:
- 选择基准值 :从数组中选择一个基准值,通常选择中间值
q[(l + r) / 2]
。 - 分割过程 :通过两个指针
i
和j
,分别从左右两边向中间移动,调整元素位置swap,确保左边的元素小于基准值,右边的元素大于基准值。 - 交换元素:当左边的元素大于基准值且右边的元素小于基准值时,交换它们的位置。
- 递归调用:将分好的两个子数组递归地进行快速排序。
代码解析:
void quick_sort(int q[], int l, int r) { if (l >= r) return; // 递归基准条件 int i = l - 1, j = r + 1, x = q[(l + r) / 2]; // 基准值为中间值 while (i < j) { do i++; while (q[i] < x); // 找到左边比基准值大的数 do j--; while (q[j] > x); // 找到右边比基准值小的数 if (i < j) swap(q[i], q[j]); // 交换 } quick_sort(q, l, j); // 递归左边子数组 quick_sort(q, j + 1, r); // 递归右边子数组 }
关键点:
- 分治法:选择基准值后将数组分为两部分,左边小于基准,右边大于基准。
- 双指针 :
i
和j
分别从左边和右边移动,直到找到需要交换的元素。 - 递归:对左右子数组分别进行快速排序。
2. 归并排序算法(Merge Sort)
思考过程:
归并排序也是分治法的一种,通过不断地将数组分为两个子数组,直到子数组的大小为 1。然后通过 合并操作,将两个有序子数组合并成一个有序的大数组,递归地合并直到整个数组有序。
具体步骤:
- 分割过程:将数组分成两部分,分别对每个部分进行排序。直到每个部分的大小为 1。
- 合并过程:将两个已经排序的子数组合并为一个有序数组。在合并过程中,利用两个指针分别指向两个子数组,选择较小的元素放入结果数组。
代码解析:
void merge_sort(int q[], int l, int r) { if (l >= r) return; // 递归基准条件 int mid = (l + r) >> 1; // 中间位置 merge_sort(q, l, mid); // 递归左边 merge_sort(q, mid + 1, r); // 递归右边 int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) // 合并两个有序子数组 if (q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; while (i <= mid) tmp[k++] = q[i++]; // 左边数组剩余元素 while (j <= r) tmp[k++] = q[j++]; // 右边数组剩余元素 for (i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j]; // 将合并后的结果拷贝回原数组 }
关键点:
- 分治法:递归地将数组拆分成两部分,直到每部分只有一个元素。
- 合并过程:合并两个已经排好序的子数组,通过比较每个子数组的最小元素,将它们合并成一个有序数组。
- 辅助数组 :
tmp[]
用来暂存合并后的结果。
快速排序例题
快速排序acwinghttps://www.acwing.com/problem/content/787/
1.给定你一个长度为 nn 的整数数列。
请你使用快速排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n个整数(所有整数均在 1∼10......9范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
1≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
cpp
#include <iostream>
using namespace std;
int a[100000];
int n;
void quick(int a[], int l, int r) {
if (l >= r) return; // 递归的终止条件:当子数组只有一个或没有元素时停止
int i = l-1, j = r+1; // i 从 l,j 从 r 初始化
int x = a[(l + r) / 2]; // 选择基准元素为中间元素
while (i <= j) { // 当 i 和 j 不交错时,继续划分
// 向右移动 i,直到找到一个大于或等于基准的元素
do i++; while (a[i] < x);
// 向左移动 j,直到找到一个小于或等于基准的元素
do j--; while (a[j] > x);
if (i <= j) {
// 如果 i 小于等于 j,交换 a[i] 和 a[j]
swap(a[i], a[j]);
}
}
// 递归调用对左半部分和右半部分进行排序
quick(a, l, j);
quick(a, i, r);
}
int main() {
cin >> n; // 输入数组大小
for (int i = 0; i < n; i++) {
cin >> a[i]; // 输入数组元素
}
quick(a, 0, n - 1); // 调用快速排序
for (int i = 0; i < n; i++) {
cout << a[i] << " "; // 输出排序后的数组
}
return 0;
}
归并排序例题
归并https://www.acwing.com/problem/content/789/
cpp
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N];
int temp[N];
// 合并函数:将两个已排序的子数组合并
void merge(int a[], int l, int r) {
if (l >= r) return; // 递归的终止条件,当子数组只有一个元素时返回
int mid = (l + r) / 2; // 找到中间点
// 递归拆分数组
merge(a, l, mid);
merge(a, mid + 1, r);
int i = l, j = mid + 1, k = l; // 初始化指针,i 和 j 分别指向左右子数组,k 用于填充 temp 数组
while (i <= mid && j <= r) { // 比较左右子数组的元素
if (a[i] <= a[j]) {
temp[k++] = a[i++]; // 如果左子数组的元素小于等于右子数组的元素,放入 temp
} else {
temp[k++] = a[j++]; // 否则,放入右子数组的元素
}
}
// 复制左子数组剩余的元素
while (i <= mid) {
temp[k++] = a[i++];
}
// 复制右子数组剩余的元素
while (j <= r) {
temp[k++] = a[j++];
}
// 将临时数组中的元素复制回原数组
for (int i = l; i <= r; i++) {
a[i] = temp[i];
}
}
int main() {
cin >> n; // 输入数组的大小
for (int i = 0; i < n; i++) {
cin >> a[i]; // 输入数组元素
}
merge(a, 0, n - 1); // 调用归并排序函数
// 输出排序后的数组
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
return 0;
}