写在前面:
四月蓝桥杯迫在眉睫,被迫营业总结笔记。
一 排序
1 快速排序
(1)算法思想:
1)确定分界点 q[l],q[r],q[(l+r)/2],随机。(不同的分界点对快排影响特别大,同时也影响边界);
2)调整区间(快排算法关键)。通过两个指针i,j,区间左边存放不大于分界点的值,右边存放不小于分界点的值。
3)递归处理分别左右两段(选取不同分界点递归接口不同)
(2)算法实现
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l+r+1>>1];//因为i,j都是先移动再判断,故取i=l-1,j=r+1;
while (i < j)//调整区间(一般情况下结束后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, i-1);
quick_sort(q, i, r);
}
结束后i和j关系有两种情况,i==j或者i=j+1;
值得注意的是当分界点取q[l],q[l+1 >>1]时,递归处理端口不能取
quick_sort(q, l, i-1);
quick_sort(q, i, r);
当n=2,分别取2,3时
quick_sort(q,l,i-1)取quick_sort(q,0,-1)结束递归;
quick_sort(q,i,r)取quick_sort(q,0,1)循环递归
同理当分界点取q[r],q[l+r+1 >>1]时,递归端口不能取
quick_sort(q, l, j);
quick_sort(q, j+1, r);
2.归并排序
(1)算法思想
1)确定分界点,mid=l+1 >>1;(使归并排序稳定在nlogn)
2) 递归排序
3)归并,合二为一
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 i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
if(q[i]<=q[j]) temp[k++]=q[i++];
else temp[k++]=q[j++];
while(i<=mid)temp[k++]=q[i++];
while(j<=r)temp[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++)q[i]=temp[j];
}
二 . 二分
在一段可以分成"性质"明显不同的两端(可以是递增序列),可以通过二分不断缩小答案区间的算法就是二分。
1.整数二分
难点在于端点的选取,操作不当容易造成死循环
整数二分有两种模型
1)当x<=q[mid]
r=mid,l=mid+1;
int l=0,r=n-1;
while(l<r)
{
int mid=(l+r) >>1;
if(q[mid]>=x)r=mid;
else
l=mid+1;
}
2) x>=q[mid]
l=mid,r=mid-1;值得注意的是这里mid=(l+r+1)>>1(向上取整),
当l=a-1,r=a时,如果mid=l+r >>1=a-1,当符合if判断条件则l=mid=a-1则会出现死循环
while(l<r)
{
int mid=(l+r+1) >>1;
if(q[mid]<=x)l=mid;
else
r=mid-1;
}
2浮点数二分
浮点数除2不用考虑取整情况比较简单,l=mid,r=mid即可
用二分实现开三方代码如下
double l=-100,r=100;
while(r-l>1e-8)
{
double mid=(l+r)/2;
if(mid*mid*mid>=x)r=mid;
else
l=mid;
}
如要得到带小数点后面a位的浮点数,为了保持精度,r-l的差值一般取小于1e-(a+2)
写在后面:
如有错误,欢迎巨巨们斧正!