1、快速排序
①在数组中任找一值作为分界点,如l+r>>1;
②调整区间,使得第一个区间所有的数<=x,第二个区间所有的数>=x;(用到do while循环,出口条件循环,先执行循环体,再判断表达式)
③递归处理左右两段。
#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+r>>1];
int i = l-1;
int 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]);
}
}//排序前i在j的左,排序完j在i的左侧
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main()
{
int n;
for(int i= 0;i<n;i++)
{
cin>>q[i];
}
quick_sort(q,0,n-1);
for(int i = 0;i<n;i++) cout<<q[i];
return 0;
}
2、归并排序
①确定分界数,mid = l+r>>1;
②递归排序left,right;
③归并合二为一,将两个有序数组合为一个有序数组。故此处需要一个临时数组,将数据元素放入后,再将临时数组的值放回原数组。
#include<iostream>
using namespace std;
const int N = 1e6+10;
int q[N],temp[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);
//开始归并,将两个有序的序列放入temp中
int k = 0;i =l; j = mid+1;
while(i<=mid&&j<=r)// 两组 没有任何一个指针移动到终点时
{ //上下两组比较大小。将数值小的放入临时数组中,并移位
//tmp[k++] = q[i++]等价于tmp[k] = q[i];k++;i++; q[i++]是先赋值再自增
if(q[i]<=q[j]) temp[k++] = q[i++];//
else temp[k++] = q[j++];
}
//此时,有一组循环完毕,结束当前while循环
while(i<=mid) temp[k++] = q[i++];//如果左半边没有循环完,将剩余元素放入新的数组中
while(j<=r) temp[k++] = q[j++];//如果右半边没有循环完,将剩余元素放入新的数组中
//注意这里是字母l不是数字1
for(i =l,j = 0;i< =r;i++,j++) q[i] =temp[j];//将临时数组中的元素复制回原数组
}
int main()
{
int n;
cin>>n;
for(int i = 0;i<n;i++) cin>>p[i];
merge_sort(q,0,n-1);
for(int i = 0;i<n;i++) cout<<p[i];
return 0;
}
3、二分
3.1整数二分
更新区间为l= mid则mid分子需要补+1;因为是下取整
更新区间为r = mid则更新区间不需要补。
(1)先找红色区域边界。mid = (l+r+1)/2,mid满足红色性质,所以mid在l到边界点之间,要找边界点,就要往mid右边去找,所以check(mid)是true那么它的边界点的范围在[mid,r]之间,更新方式l =mid。当check(mid)为false时,mid一定取在绿色区域,则边界点在[l,mid-1]之间,更新方式r = mid-1。
(2)找绿色区域边界点,mid = (l+r)/2,mid满足绿色性质,所以mid在边界点到r之间,所以check(mid)是true那么边界点范围在[l,mid]之间,更新方式r = mid。所以check(mid)是false时,边界点在[mid+1,r]之间,更新方式l = mid+1。
#include<iostream>
using namespace std;
const int N = 1e6+10;
int n,q;
int p[N];
int x;
int main()
{
cin>>n;
cin>>q;
for(int i=0;i<n;i++)
{
cin>>p[i];
}
while(q--)
{
int l = 0;
int r = n-1;
cin>>x;
while(l<r)
{
int mid = (l+r)>>1;
//先看大于,右边。更新边界。
if(p[mid]>=x) r=mid;
else l = mid+1;
}
if(p[l]!=x) cout<<"-1 -1"<<endl;
else
{
cout<<l<<" ";
int l = 0;
int r = n-1;
while(l<r)
{
int mid = (l+r+1)>>1;
if(p[mid]<=x) l=mid;
else r = mid-1;
}
cout<<l<<endl;
}
}
return 0;
}
3.2浮点数二分
保留4位小数e-6,5位小数e-7,6位小数e-8。