一)问题描述:
对n个元素进行排序。
二)基本思路:
将待排序的n个元素先从中间,即n/2的位置进行分解(如果是奇数,可以考虑将多出来的元素放入前半部分或者后半部分,一旦确定是前半部分或者后半部分,则要求以后的操作均以这一次为标准,都放入前半部分或后半部分),一直分解到单个元素为一个组,之后两两拼合。
分解:
合并:
三)代码
主函数:
//主函数
public static void main(String[] args) {
MergeSort k=new MergeSort();
k.mergeSort();
System.out.println(k);
}
因为,虽然要分解,但是都是分解到最后一个元素,所以,可以直接两两合并,不进行递归的分解。
//类,及其初始化
public class MergeSort {
int[] a;
int[] b;
int n;
int left;
int right;
public MergeSort() {
this.initialize();
}
@SuppressWarnings("resource")
public void initialize() {
System.out.println("please enter the number you want to sort:");
Scanner number=new Scanner(System.in);
this.n=number.nextInt();
if(n<2)
{
return ;
}
//初始化数组
a=new int[n];
b=new int[n];
for(int i=0;i<n;i++)
{
a[i]=0;
b[i]=0;
}
//正式赋值
System.out.println("please enter the number:");
for(int i=0;i<n;i++)
{
Scanner c=new Scanner(System.in);
this.a[i]=c.nextInt();
}
}
说明:mergeSort():将已有a[] 按照s个元素进行依次合并;
public void mergeSort() {
int s=1;
while(s<n) {//当s<n时,进行分解
this.mergePass(s);//统一放在x中
s+=s;
}
}
说明:mergePass():将a[]按照s分解,更新;
public void mergePass(int s) {
int i=0;
while(i<n-2*s) {//比如n=5;第一次就是i<3即前三个,也就是会留下剩下的3、4为一组,之前的为一组
merge(i,i+s-1,i+2*s-1);
i=i+2*s;
}
if(i+s<n){merge(i,i+s-1,n-1);}
else {
for(int j=i;j<=n-1;j++) {b[j]=a[j];}
}
for(int k=0;k<n;k++)
{a[k]=b[k];//这里相当重要,因为是都在一个数组上面操作,所以需要每次都更新数组a}
}
说明:merge():将数组分开的部分进行合并
public void merge(int f,int m,int e) {
int i=f;
int j=m+1;
int k=f;
while((i<=m)&&(j<=e))
{
if(a[i]<=a[j]) {b[k++]=a[i++];}
else {b[k++]=a[j++];}
}
//将刚才没有添进去的元素添进去;
if(i>m)//时第一部分没有添加完毕,所以将第二部分添加进去;
{
for(int q=j;q<=e;q++)
{ b[k++]=a[q];}
}
if(j>e)
{
for(int q=i;q<=m;q++)
{ b[k++]=a[q];}
}
}
说明:输出
public String toString() {
for(int i=0;i<n;i++)
{System.out.print(b[i]+" ");}
return "";
}
结果:
时间复杂度:
O(n logn)