排序算法之归并排序

基本思想:

设归并排序的当前区间是R[low..high],分治法的三个步骤是: 
①分解:将当前区间一分为二,即求分裂点 
                 
②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序; 
③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。 
  递归的终结条件:子区间长度为1(一个记录自然有序)。

 

将两个有序序列合并成一个新的有序序列。(归并排序将数组分成一个一个元素,一个元素默认有序,从一个元素的数组开始合并起,往后的多个元素的数组是建立在前面的基础上(已经具备有序性)再进行归并的)

①把 n 个记录看成 n 个长度为 1的有序子表; 
②进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表; 
③重复第②步直到所有记录归并成一个长度为 n 的有序表为止

重点:

1.分治的实现

2.合并的实现

分治,就是把整个集合的元素一直除2化分,一直化为到一个数组没有两个元素开始合并。

对于归并排序,其关键就在于“合并”,即如何将两个有序序列合并成一个新的有序序列。

合并的思路:新建一个数组用来存储合并总的数据,逐个判断两个数组中元素的大小,将小的放入到新数组中,并将索引加1

java代码实现:

package fanzhenhua.sort;

import java.util.Arrays;

public class MergeSort {
	public static void mergeSort(DataWrap[] data){
		sort(data,0,data.length-1);
	}
	private static void sort(DataWrap[] data,int left,int right){
		//将数组一直分割下去,直到分割后的数组元素个数为1为止,也就是left>=right时就停止分割
		if(left<right){
			//计算分割的中点,该点默认为左边数组最后一个元素
			int center=(left+right)/2;
			//左分割
			sort(data,left,center);
			//右分割
			sort(data,center+1,right);
			//合并分割后的左右数组为一个数组
			merge(data,left,center,right);
			System.out.println(Arrays.toString(data));
		}
	}
	
	//将两个有序数组进行合并
	private static void merge(DataWrap[] data,int left,int center,int right){
		//构建一个新的数组用来存放排序过程中的数据
		DataWrap[] newData=new DataWrap[data.length];
		//获取右边数组的第一个数据索引
		int mid=center+1;
		//定义两个中间变量,index1表示左边数组的第一个位置,index2表示newData数组的起始位置。
		int index1=left;
		int index2=left;
		//分别对左边数组和右边数组中的数据进行比较判断,并添加进新数组中。(这种方法要求待归并的两个数组必须有序)
		//归并排序利用递归的思想,将数组划分成一个元素一个元素的数组(一个元素的数组默认有序),先从一个元素的数组排序起
		//往后的数组在之前排好序的基础上在进行归并
		while(left<=center&&mid<=right){
			//如果左边的小于右边的,则将左边数组的数据添加入新的数组中
			if(data[left].compareTo(data[mid])<=0){
				newData[index1++]=data[left++];
			}else{//否则的话将右边数组的数据添加入新的数组中
				newData[index1++]=data[mid++];
			}
		}
		while(left<=center){
			newData[index1++]=data[left++];
		}
		while(mid<=right){
			newData[index1++]=data[mid++];
		}
		while(index2<=right){
			data[index2]=newData[index2++];
		}
		
	}
	public static void main(String[] args) {
		DataWrap[] data = {
				new DataWrap(25, "")
				,new DataWrap(-16, "")
				,new DataWrap(15, "")
				,new DataWrap(23, "")
				,new DataWrap(-30, "")
				,new DataWrap(-49, "")
				,new DataWrap(21, "*")
				,new DataWrap(30, "")
				,new DataWrap(3, "")
				,new DataWrap(67, "")
				,new DataWrap(35, "")
				,new DataWrap(5, "")
				,new DataWrap(7, "")
				,new DataWrap(21, "")
				,new DataWrap(49, "")
		};
		
		System.out.println("排序之前:" + Arrays.toString(data));
		mergeSort(data);
		System.out.println("排序之后:" + Arrays.toString(data));
	}
	
}

排序过程以及结果:

算法分析:

1、稳定性 
     归并排序是一种稳定的排序。 
2、存储结构要求 
    可用顺序存储结构。也易于在链表上实现。 
3、时间复杂度 
    对长度为n的文件,需进行 lgn趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
4、空间复杂度 
    需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
 

参考文章:

https://blog.csdn.net/bruce_6/article/details/39121643

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值