萌新学习算法——归并排序基础
归并排序是分治法的一个典型例子,首先讲一下分治法,分治法是将一个难以直接理解大问题划分为一些规模小的子问题,分别求解各个子问题,再合并子问题的解得到原问题的解。一般来说,分治法的求解过程由三部分组成:
步骤
1. 划分:把规模为n的原问题划分为k个(通常k=2)规模较小的子问题;
2. 求解子问题:各子问题的解法与原问题的解法通常是相同的,可以用递归的方法求解各个子问题,有时递归处理也可以用循环来实现;
3. 合并:把各个子问题的解合并起来,合并的代价因情况不同有很大差异,分治算法的效率很大程度上依赖于合并的实现
接下来我们运用分治法的思想来实现归并排序:
步骤:
1. 划分:将待排序序列R1,R2,…Rn划分为两个长度相同的子序列R1,R2,…Rn/2和Rn/2+1,…Rn;
2. 求解子问题:分别对这两个子序列进行排序,得到两个有序子序列;
3. 合并:将这连个有序子序列合成一个有序序列。
归并算法(经典版)
我们将代码分成两段,一段是用于排序的,一段是用于合并的,我们来看一下代码实现从小到大排序。
代码:
定义的变量:
public static int temp[]=new int[10],data[]= {2,1,3,5,4,7,6,10,9,8};//temp数组用来保存临时的值
合并操作merge方法:
public static void Merge(int start,int end,int mid) //传入数组的开始下标,结束下标和分割的点
{
int i=start,j=mid+1,k=start; //i保存左边的开始下标,j保存
while(i<=mid&&j<=end) //右边的下标不大于end,左边下标不大于mid,单其中一个条件不满足则结束
{
if(data[i]<=data[j])
temp[k++]=data[i++];
else
temp[k++]=data[j++];
}
//将剩下的值直接插入末尾
while(i<=mid)
temp[k++]=data[i++];
while(j<=end)
temp[k++]=data[j++];
//将排好序的temp数组逐一加入data数组
for(i=start;i<=end;i++)
data[i]=temp[i];
}
归并排序mergeSort方法:
public static void mergeSort(int start,int end)
{
if(start>=end) return ; //退出递归的条件
int mid=(start+end)/2; //找到分割点
mergeSort(start, mid); //左边的数进行排序
mergeSort(mid+1, end);//右边的数进行排序
Merge(start, end, mid);//将左右两边合并
}
main方法:
public static void main(String[] args) {
mergeSort(0, 9);
for(int i=0;i<10;i++)
System.out.print(data[i]+" ");
}
运行结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191208104000529.png
归并排序(简化版)
在这里我们可以对归并排序进行简化,将合并和排序合成一个方法实现:
public static void mergeSort(int start,int end)// 开始的下标,结束的下标
{
if(start>=end) return ; // 退出递归的条件
int mid=(start+end)/2;
mergeSort(start, mid); //递归左边的
mergeSort(mid+1, end); //递归右边的
int i=start,j=mid+1,k=start;
while(i<=mid&&j<=end)
{
if(data[i]<=data[j])
temp[k++]=data[i++];
else
temp[k++]=data[j++];
}
//将剩下的直接加入数组的尾部
while(i<=mid)
temp[k++]=data[i++];
while(j<=end)
temp[k++]=data[j++];
//合并
for(i=start;i<=end;i++)
data[i]=temp[i];
}
完整代码:
public class Main {
public static int temp[]=new int[10],data[]= {2,1,3,5,4,7,6,10,9,8};//temp数组用来保存临时的值
public static void mergeSort(int start,int end)// 开始的下标,结束的下标
{
if(start>=end) return ; // 退出递归的条件
int mid=(start+end)/2;
mergeSort(start, mid); //递归左边的
mergeSort(mid+1, end); //递归右边的
int i=start,j=mid+1,k=start;
while(i<=mid&&j<=end)
{
if(data[i]<=data[j])
temp[k++]=data[i++];
else
temp[k++]=data[j++];
}
//将剩下的直接加入数组的尾部
while(i<=mid)
temp[k++]=data[i++];
while(j<=end)
temp[k++]=data[j++];
//合并
for(i=start;i<=end;i++)
data[i]=temp[i];
}
public static void main(String[] args) {
mergeSort(0, 9);
for(int i=0;i<10;i++)
System.out.print(data[i]+" ");
}
}