一.快速排序
快速排序模板
思路:
-
判断l与r,记得return
-
定义基数x、i和j,基数可以是x=q[l],最好是x=q[r+l>>1],原因:防止碰到有序数组
-
判断i从左边走,要时刻满足<基数x,j从右边走,要时刻满足>基数x,直到指针i与j相遇,swap i与j所对应的函数值
-
第一次i与j相遇的时候,把数组分为了左右区间,在分别对左右区间进行快速排序
左右区间可以分别是(l,j)和(j+1,r)也可以是(l,i-1)和(i,r)
上代码:
//quick_sort
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
void quick_sort(int q[], int l, int r) {
if (l >= r)
return;
int x = q[l], i = l - 1, j = r + 1;//基数x用q[l+r>>1]比较好,防止碰到有序数组
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);
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &q[i]);
quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", q[i]);
return 0;
}
快速排序例题
#include <iostream>
using namespace std;
const int N = 1000010;
int n, k;
int q[N];
void quick_sort(int q[], int l, int r) {//快排模板
if (l >= r)
return ;
int x = q[l + r >> 1], i = l - 1, j = r + 1;
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);
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++)
scanf("%d", &q[i]);
quick_sort(q, 0, n - 1);
printf("%d", q[k]);//求第k小数,输出q[k]就行了
}
归并排序
归并排序模板
思路:
- 将[L,R]分成两个区间[L,mid]和[mid+1,R]
- 递归排序[L,mid]和[mid+1,R]
- 归并,将左右两个有序序列合并成一个有序序列(q[i]与q[j]比较大小,小的进tmp数组里面)
- 别忘了扫尾
- 最后物归原主,把tmp还到q数组里面
代码
#include <iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N], tmp[N];
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];
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &q[i]);
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", q[i]);
return 0;
}
归并排序例题
分析题目:
- 左半边内部的逆序对数量:merge_sort(L,mid)
右半边内部的逆序对数量:merge_sort(mid+1,R)
(merge_sort函数返回逆序对的数量)
ll res = merge_sort(l,mid)+merge_sort(mid+1,r);
- 由于默认原序列是有序的,所以正在排序的两个区间也都是有序的
当q[i]<q[j]时,q[i~mid]的所有数,都可以与q[i]构成逆序对
所以res+=mid-i+1;
- 扫尾
- 物归原主
#include <iostream>
using namespace std;
const int N = 500010;
typedef long long ll;
int n;
int q[N], tmp[N];
ll merge_sort(int l, int r) {
if (l >= r)
return 0;
int mid = r + l >> 1;
ll res = merge_sort(l, mid) + merge_sort(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 {//由于正在排序的两个区间都是有序的
//当q[i]>q[j]时,q[i~mid]的所有数,都可以与q[i]构成逆序对
res += mid - i + 1;
tmp[k++] = q[j++];
}
//扫尾
while (i <= mid)
tmp[k++] = q[i++];
while (j <= r)
tmp[k++] = q[j++];
//物归原主
for (int i = l, j = 0; i <= r; i++, j++)
q[i] = tmp[j];
return res;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++)
cin >> q[i];
cout << merge_sort(0, n - 1);
return 0;
}
最后
总结:
这两种排序掌握思想,比赛中有对应函数sort来代替
sort()函数:
头文件#include
sort(begin,end,cmp)不加cmp默认是升序
需要的话,自己写cmp函数
bool cmp(int a,int b){
return a<b;//降序用小于
}
bool cmp(int a,int b){
return a>b;//升序用大于
}