1、快速排序
首先确定分界点:可以是q[l], q[mid], q[r],随机
然后调整区间让left指针左边的都比边界值小,right右边的都比边界值大
最后递归处理左右两端
注意:
当使用q[l]为分界值时处理两边时就不用i防止边界问题出现无限递归的情况
当使用q[r]为分界值时就不要用j
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;//每次比较完先移动,所以移动完才到数列边界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);
}
2、归并排序
首先确定分界点:mid = (l + r) / 2
递归排序左右两边
最后归并,使用tmp存放两边中较小的当其中一个全部比完后就可以将另一边后面全部加入tmp
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]
}
3、二分
时间复杂度是logn
每次二分保证答案落在区间里面
在区分找左边界还是右边界时是根据check函数决定的
关键点是将定义的mid点保证在需要的范围中
找左边就是 q[mid] <= x
找右边就是 q[mid] >= x 就是q[mid] 符号的范围
寻找的范围是左闭右闭
如果是l = mid 就需要在mid = l + r + 1 >> 1;
如果是r = mid 就不需要
整数二分
通过判断mid是否符合某一边的性质来判断边界点与mid的位置使其无限接近
//区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(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]被划分成[l, mid - 1]和[mid, r]时使用,在定左边区域的边界
int brearch_2(int l, int r)
{
while(l < r)
{
int mid = l + r + 1 >> 1;//狠狠的补,check满足的性质在划分的左边
if(check(mid)) l = mid; //l等于mid就需要补上加1
else r = mid - 1;
}
return 1;
}
浮点数二分
例:求一个数的平方根
#include<iostream>
using namespace std;
int main()
{
double x;
cin>>x;
double l = 0, r = x;
while(l - r > 1e-8)
{
double mid = l + r / 2;
if(mid * mid > x) r = mid;//一个半边需要满足的性质,更新保证答案落在区间里面
else l = mid;
}
printf("%f\n", l);
return 0;
}
以上内容学习自AcWing