一、快速排序(分治思想)
快速排序步骤
1、确定分界点,q[left], q[(left+right+1)/2], q[right](左边界点、中间边界点和右边界点取其一,建议取中间,避免出现死循环);
2、调整范围,分界点左边的数小于等于边界点,右边的数大于等边界点;
3、递归分别处理左右两端。
#include<iostream>
using namespace std;
const int N = 1e5 + 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;
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;
}
二、归并排序(分治思想)
1、确定分界点(此为确定数组位置而非数值);
2、递归排序;
3、归并----数组合二为一
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
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;
}
三、二分查找
3.1整数二分
重点:单调性必能二分,满足某一性质也能二分(性质根据题目)
划分区间和更新方式如下图
//区间[l, r]划分成[1, mid]和[mid+1, r]使用
int bsearch(int l, int r)
{
while(l < r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid; //check()判断mid是否满足性质
else l = mid + 1;
}
return 1;
}
//区间[l, r]划分成[1, mid - 1]和[mid, r]使用
int bsearch(int l, int r)
{
while(l < r)
{
int mid = l + r + 1>> 1;
if(check(mid)) l = mid; //check()判断mid是否满足性质
else r = mid - 1;
}
return 1;
}
3.2浮点数二分
不需要考虑边界问题
bool check(double x) {/* ... */} // 检查x是否满足某种性质
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}