1.快速排序
解题代码
#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)/2], 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;
}
分析代码
#include<iostream>
using namespace std;
const int N = 1e6 + 10;//1*10^6+10=1000010
int n;
int q[N];
void quick_sort(int q[],int l,int r)
{
if(l>=r)return;
int x = q[(l+r)/2], i = l - 1, j = r + 1;//指针i,j
//cout<<"l="<<l<<" r="<<r<<endl;
//cout<<"当前序列";
//for(int i=l;i<=r;i++) printf("%d ",q[i]);
//cout<<endl;
//cout<<"x=q[l]="<<x<<endl;
while(i<j)
{
do{i++;/*cout<<"while循环中i="<<i<<endl;*/}while(q[i]<x);
//do i++;while(q[i]<x);
//do j--;while(q[j]>x);
do{j--;/*cout<<"while循环中j="<<j<<endl;*/}while(q[j]>x);
//cout<<"两次循环后i="<<i<<" j="<<j<<endl;
if(i<j) swap(q[i],q[j]);
}
// cout<<"j="<<j<<"处理后的序列";
//for(int i=l;i<=r;i++) printf("%d ",q[i]);
//cout<<endl;
//递归处理左右两端
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;
}
2.归并排序
//输入
7
6 4 3 7 5 1 2
//输出
1 2 3 4 5 6 7
归并:解题代码
#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;
}
归并:分析代码
#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)
{
cout<<"函数内部l="<<l<<",r="<<r<<endl;
if(l>=r)
{
cout<<"回溯,l="<<l<<",r="<<r<<endl;
return;
}
//取上中位数
int mid = l + r >> 1;
//用递归拆分,直到拆为两个数
cout<<"递归左边"<<endl;
cout<<"递归前l="<<l<<",r="<<r<<" mid="<<mid<<endl;
merge_sort(q,l,mid);
cout<<"递归右边"<<endl;
cout<<"递归前l="<<l<<",r="<<r<<" mid="<<mid<<endl;
merge_sort(q,mid+1,r);
cout<<"递归结束"<<endl;
//cout<<"递归后l="<<l<<",r="<<r<<l<<" mid="<<mid<<endl;
//k是tmp[]有多少个数,k[0]=q[2]
int k=0,i=l,j=mid+1;
//合并
cout<<"合并前i="<<i<<" j="<<j<<endl;
while(i<=mid && j<=r)
if(q[i]<=q[j])
{
cout<<"给tmp赋值 tmp["<<k<<"]=q["<<i<<"]"<<endl;
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.二分
二分-解题代码
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int q[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
while (m -- )
{
int x;
scanf("%d", &x);
int l = 0, r = n - 1;
while (l < r)
{
int mid = l + r >> 1;
if (q[mid] >= x) r = mid;
else l = mid + 1;
}
if (q[l] != x) cout << "-1 -1" << endl;
else
{
cout << l << ' ';
int l = 0, r = n - 1;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (q[mid] <= x) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
}
return 0;
}
二分-分析代码
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;//m为查询的次数
int q[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
while (m -- )
{
int x;//查询x在数列中的开始和结束位置
scanf("%d", &x);
int l = 0, r = n - 1;
while (l < r)
{
cout<<"mid为上中位数"<<endl;
int mid = l + r >> 1;//上中位数,较小位置,作结束位
if (q[mid] >= x) //较小位置的数>=x
{
cout<<"前半部分找"<<endl;
r = mid; //x在mid 前面,下一次应该在前半部分找
}
else //较小位置的数<x
{
cout<<"后半部分找"<<endl;
l = mid + 1; //x在mid后面,下一次应该在后半部分找
}
cout<<x<<"可能在l="<<l<<",r="<<r<<endl;
}
if (q[l] != x) cout << "-1 -1" << endl;
else
{
cout<<"最终x开始的位置在";
cout << l << ' '; //开始的位置
int l = 0, r = n - 1;
while (l < r)
{
cout<<"mid为下中位数"<<endl;
int mid = l + r + 1 >> 1;//下中位数,较大位置,作开始位
if (q[mid] <= x) //较大位置的数<=x
{
cout<<"后半部分找"<<endl;
l = mid; //x在mid后面,下一次应该在后半部分找
}
else //较大位置的数>x
{
cout<<"前半部分找"<<endl;
r = mid - 1; //x在mid 前面,下一次应该在前半部分找
}
cout<<x<<"可能在l="<<l<<",r="<<r<<endl;
}
cout<<"最终x结束的位置在";
cout << l << endl; //结束的位置
}
}
return 0;
}