分治法思路:
1.分解:把大问题分解为若干个小问题
2.解决:递归地解决各个小问题,当子问题的规模足够小,则直接求解
3.合并:合并各个小问题的解,从而得到大问题的解
归并排序排序:
1.分解:分解带排序的n个元素的序列,使其分成各具有n/2个元素的两个子序列
2.解决:使用归并排序递归地排序两个子序列
3.合并:合并两个已排好序的子序列
//归并排序(小到大,有哨兵)
#include <iostream>
using namespace std;
void merge_sort(int a[],int top,int bott);
void merge(int a[],int top,int mid,int bott);
const int maxn=10000;
int main()
{
int a[maxn];
int n,i;
cin>>n;
for (i=0;i<n;i++)
cin>>a[i];
merge_sort(a,0,n-1);//进入归并排序
for (i=0;i<n;i++)
cout<<a[i]<<' ';
cout<<endl;
return 0;
}
//merge_sort
void merge_sort(int a[],int p,int r)
{
int q;
if (p<r)
{
q=(p+r)/2;
merge_sort(a,p,q);//左边排序
merge_sort(a,q+1,r);//右边排序
merge(a,p,q,r);//合并
}
}
//merge
void merge(int a[],int p,int q,int r)
{
int left[maxn],right[maxn];
int n1,n2,i,j,k;
n1=q-p+1;//左边的元素个数
n2=r-q;//右边的元素个数
for (i=0;i<n1;i++)
left[i]=a[p+i];//把a中的前半元素复制到left
for (j=0;j<n2;j++)
right[j]=a[q+1+j];//把a中的后半元素复制到right
left[n1]=99999;//左边的哨兵
right[n2]=99999;//右边的哨兵
i=0;//左边的下标
j=0;//右边的下标
//把left和right重新复制回a,使a成为排好序的序列
for (k=p;k<=r;k++)
{
if (left[i]<=right[j])
{
a[k]=left[i];
i++;
}
else
{
a[k]=right[j];
j++;
}
}
}
//归并排序(小到大,无哨兵)
#include <iostream>
using namespace std;
void merge_sort(int a[],int top,int bott);
void merge(int a[],int top,int mid,int bott);
const int maxn=10000;
int main()
{
int a[maxn];
int n,i;
cin>>n;
for (i=0;i<n;i++)
cin>>a[i];
merge_sort(a,0,n-1);//进入归并排序
for (i=0;i<n;i++)
cout<<a[i]<<' ';
cout<<endl;
return 0;
}
//merge_sort
void merge_sort(int a[],int p,int r)
{
int q;
if (p<r)
{
q=(p+r)/2;
merge_sort(a,p,q);//左边排序
merge_sort(a,q+1,r);//右边排序
merge(a,p,q,r);//合并
}
}
//merge
void merge(int a[],int p,int q,int r)
{
int left[maxn],right[maxn];
int n1,n2,i,j,k;
n1=q-p+1;//左边的元素个数
n2=r-q;//右边的元素个数
for (i=0;i<n1;i++)
left[i]=a[p+i];//把a中的前半元素复制到left
for (j=0;j<n2;j++)
right[j]=a[q+1+j];//把a中的后半元素复制到right
i=0;//左边的下标
j=0;//右边的下标
//把left和right重新复制回a,使a成为排好序的序列
for (k=p;k<=r;k++)
{
if (i==n1) //当left已没有元素,将right剩余的元素复制到a中
{
a[k]=right[j];
j++;
}
else if(j==n2) //当right已没有元素,将left剩余的元素复制到a中
{
a[k]=left[i];
i++;
}
else //当left和right均还有元素时,比较当前left[i]和right[i]的大小,将小的复制回a中
{
if (left[i]<=right[j])
{
a[k]=left[i];
i++;
}
else
{
a[k]=right[j];
j++;
}
}
}
}