归并排序总结

在这里插入图片描述上面是韩顺平老师的PPT中的图片
可以看到归并排序整体的思想还是挺容易理解的,先分,分到不能再分,然后再合,主要是采用递归的手段
关于递归,其实可以这样来粗略地理解它的思想:就是我当前的程序不想自己处理所有问题,而把部分问题抛给我的下一级,跟下一级说,只要你能把我交给你的解决,同时把结果返回给我,那我拿到了你的结果,我的所有问题就迎刃而解了
很多问题都用递归的手段解决,但是对于不同的具体的问题,怎么递归,依然是一个难点,不是说随便一个问题,一拿过来之后,告诉你可以用递归的方法,然后你就立马知道怎么做了
对于一个知道要用递归手段去处理的问题,我们依然要好好思考,弄清楚两个问题:
第一,递归无非就是我当前的方法调用我自己,只是参数略有调整,但是我当前的方法中还是要给出具体的执行步骤,这样,才能让我的下一级方法,所有的后面的方法,都可以沿用这样的套路,这是最大的难点,而解决这样的一个难点,我想唯一的方法就是边写代码边思考吧,这样的一个过程会加深你对该问题的理解,等你完全可以自主写出代码并且完全理解你写的代码,而不是背的,甚至可以看出别人更好的代码是在哪里做了一些优化,减少了一些执行步骤,这样就可以说你对这个问题的理解非常深了。所以说到底,递归的思想只是一个出发点,真正依赖的还是你对具体问题的理解。
第二,终止条件是什么

public static void main(String[] args) { 
		int[] arr = {100,2,4,3,5,7,6,1,0,8};
		int[] temp = new int[arr.length];
		mergeSort(arr, 0, arr.length - 1, temp);
		System.out.println(Arrays.toString(arr));
	}
	
	//这个方法体现了算法整体的思想:先分再合
	//从代码中可以看到,所有方法的实参都是同一个arr数组和temp数组,变的只是下标
	public static void mergeSort(int[] arr,int left,int right,int[] temp){
		//先分,把当前数组一分为二
		int mid = (left + right) / 2;
		
		if (left < right) {//这里符号是严格小于,即至少传过来的数组要有2个元素,才可以先分再合
			//
			mergeSort(arr,left,mid,temp);//当前方法把问题抛下去,只要左半部分能把它的工作完成,那我这边就可以在此基础上完成我的工作
			mergeSort(arr,mid + 1,right,temp);//只要右半部分能把它的工作完成,那我这边就可以在此基础上完成我的工作
			//再合,我的工作就是把左右部分合并起来
			merge(arr,left,mid,right,temp);
		}
		
	}
	
	public static void merge(int[] arr,int left,int mid,int right,int[] temp){
		int i = left;
		int j = mid + 1;
		//因为temp只是一个临时存放arr中元素的数组,每次递归的时候它都是作为一个临时容器的,所以存放的下标每次都从0开始
		int t = 0;
		
		while (i <= mid && j <= right) {
			if (arr[i] <= arr[j]) {
				temp[t] = arr[i];
				i++;
				t++;
			}else {
				temp[t] = arr[j];
				j++;
				t++;
			}
		}
		
		while (i <= mid) {
			temp[t] = arr[i];
			t++;
			i++;
		}
		
		while (j <= right) {
			temp[t] = arr[j];
			t++;
			j++;
		}//至此,temp数组中已经临时有序存放了arr中相关部分的元素了,接下来需要把temp中的元素赋值到arr中相关部分的位置上
		
		t = 0;//t归0,准备赋回到原数组的相关位置上
		while (left <= right) {
			arr[left] = temp[t];
			t++;
			left++;
		}
	}

从代码中可以看到,它其中引入了一个temp数组,过程中可以看到,temp只是一个临时存放arr中元素的数组,每次递归的时候它都是作为一个临时容器的,所以存放的下标每次都从0开始
可以理解为归并排序的实质其实就是通过二分对数组达到真正的“触底”,即分到不能再分,分的过程是一个触底的过程,然后合的动作实际上还是在对数组本身进行直接的操作,temp只是作为一个临时容器,且每一步都是临时容器,每一步合的过程都会用到,只要保证它的容量不小于数组的长度就可以了,其实没必要一定等于。
难点在于这个分分合合的过程中对于下标的精准控制,分的时候只需要left和right下标,合的时候另外给了一个mid形参,其实不引入mid形参,直接在方法体中用到的地方写(left + right) / 2也是可以的
另外一个不同的地方是代码中分了两个方法,合的方法是单独写的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值