萌新学习算法——归并排序基础

萌新学习算法——归并排序基础

归并排序是分治法的一个典型例子,首先讲一下分治法,分治法是将一个难以直接理解大问题划分为一些规模小的子问题,分别求解各个子问题,再合并子问题的解得到原问题的解。一般来说,分治法的求解过程由三部分组成:

步骤

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]+" ");
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值