归并排序java实现

一.前提

1.为简单起见,讨论从小到大的整数排序
2.只讨论基于比较的排序(< = >有定义)
3.只讨论内部排序
4.稳定性:任意两个相等的数据,排序前后相对位置不发生变化


二.归并排序原理

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序



三.分类

1.算法1-用递归

(1)实现

   //合并时用到的临时数组
	static int[] temp;
	
	//array:要排序的数组
	//begin:要排序的数组在在array中的起始位置
	//end:要排序的数组在在array中的末尾位置
	//把数组分为两半,排好左边的,再排好右边的,合并
	static void Merge_Sort(int[] array, int begin, int end){
		//递归结束条件
		if(begin >= end) return;
		
		//如果temp=null,表示是第一次进行分割,初始化temp。temp只初始化一次
		//即只会有一个临时数组
		if(null == temp) temp = new int[array.length];
		
		//递归排好左右两边,合并
		int middle = (end - begin)/2;
		Merge_Sort(array, begin, begin+middle);
		Merge_Sort(array, begin+middle+1, end);
		merge(array, begin,end);
	}
	
	//lbegin:合并的数组在array数组中的最左位置
	//end:合并的数组在array数组中的最右位置
	static void merge(int[] array, int lbegin, int end){
		//i:temp数组的下标
		int i = 0;
		//rbegin:合并要合并两个数组,rbegin是右边数组的第一个元素的位置
		int rbegin = (lbegin+end)/2 + 1;
		int middle = rbegin;
		
		//合并到临时数组里
		while(lbegin < middle && rbegin <= end){
			if(array[lbegin] <= array[rbegin])
				temp[i++] = array[lbegin++];
			else temp[i++] = array[rbegin++];
		}
		
		//如果左右数组元素个数不相等,则把剩余的元素直接按顺序放入temp数组里
		while(lbegin < middle){
			temp[i++] = array[lbegin++];
		}
		while(rbegin <= end){
			temp[i++] = array[rbegin++];
		}
		
		//把temp数组中的元素放回array数组中
		//即表示array数组这部分合并完成
		while(i > 0){
			array[end--] = temp[i-1];
			i--;
		}
	}



(2)时间复杂度

		//递归了log(n)次
		Merge_Sort(array, begin, begin+middle);
		Merge_Sort(array, begin+middle+1, end);
		//合并的时间复杂度为O(n)
		merge(array, begin,end);
  • 总的时间复杂度:T(n) = O(nlogn)
  • 没有最好最坏,固定的nlogn



(3)空间复杂度

temp = new int[array.length];
  • 额外且只创建了一个新的数组:S1(n) = O(n);
  • 递归时压入栈的数据占用的空间:S2(n) = O(logn);
  • 空间复杂度:两者相加,取最高次的。S(n) = O(n)



2.算法2-用非递归

思路:
1.最开始把每个元素看作一个有序的子序列,然后把相邻的两个子序列归并
在这里插入图片描述2.注意:可以只开一个数组,然后两个数组重复存数据
在这里插入图片描述



六.参考

1.b站-【浙江大学】数据结构
2.csdn-超详细十大经典排序算法总结)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值