归并排序的递归,非递归实现

归并排序

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间,O(n)的额外空间。该算法是采用分治法 。
归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;

算法思路

  • 将长度为n的序列一分为二,分成子序列。
  • 子序列继续分,直到子序列只有一个数值,看做有序
  • 将有序的俩子序列归并成一个有序序列

递归程序

 public  int[] mergeSort (int array[]) {  
		   if(array.length < 2)
			   return array;
		   int mid = array.length/2;
		   int[] left =  Arrays.copyOfRange(array, 0, mid);   
		    //copy的方法是复制数组的0到mid部分,包括0不包括mid
		   int[] right = Arrays.copyOfRange(array, mid, array.length);
		     
		   return merge(mergeSort(left), mergeSort(right));//递归
		 
	   }

	   public int[] merge(int a[], int b[] ) {
	   //将俩有序子序归并成一个有序序列
	   
		   int [] c = new int[a.length + b.length ]; 
		    //定义C数组时,可不可以放到外面传入参数中直接传入一个临时数组
		    //这样可不用每次都要创建一个数组c,而是在外面一个数组中进行反复操作
		    //这样的话,不好用返回值的函数
		   int i = 0,j = 0,value = 0;   
		   while (i < a.length && j < b.length ) {
			   if(a[i] <= b[j])
				   c[value++] = a[i++];
			   else 
				   c[value++] = b[j++];
		   }
		   while(i < a.length )  
				   c[value++] = a[i++];
		   while(j < b.length )
		           c[value++] = b[j++];
		   
		   return c;
	   
	   }

上面程序中,递归之后,方法返回的是排序好的序列,但是原来序列array没有改变。需要注意。因为是在方法中返回了的merge函数,对形参进行了赋值,方法里面的形参指向了新的地址,而外面的实际参数还是原来的地址。

非递归

在这里插入图片描述
非递归的话,首先将序列都分为只有一个数值的子序列,看做有序
之后,有序的子序从1,2,4,8翻倍,一直归并,直到子序的长度大于等于数组大小

public void mergepass(int[] a, int[] tmpa, int s){ 
// s为 当前有序子列的长度
		   int i = 0;
		   while(i+2*s <= a.length ) { 
		     //i+2*s小于等于数组大小,相当于i之后未合并的的元素要大于2*s
			   merge1(a, tmpa, i, i+s, i+2*s-1);
			   i=i+2*s;
		   }
		   if(i+s < a.length ) 
		    // 未合并的元素大于s个,说明可以有俩个子列,一个长度s,一个不足s,归并
			   merge1(a, tmpa, i, i+s,a.length-1);
		   else                
		    // 未合并的元素小于等于s个,只有一个子列,直接放在临时数组后面
			   for(int j = i; j<a.length ; j++)
				   tmpa[j] = a[j];	
	   }
	   
	   
	   
	   
	   public void merge1(int[] a, int[] b, int left, int right, int rightend) { 
	   //合并有序子列成一个有序的列,假设俩有序的子列在一个数组里紧挨着
		   int leftend = right-1;
		   int tmp = left;
		   while(left <= leftend && right <= rightend) {
			   if(a[left] <= a[right])
				   b[tmp++] = a[left++];
			   else
				   b[tmp++] = a[right++];
		   }
		   while(left <= leftend)
			   b[tmp++] = a[left++];
		   while(right <= rightend)
			   b[tmp++] = a[right++];
	   }
	   
	   
	   
	   public void MergeSORT(int[] a) {
		   int[] tmpa = new int[a.length ];
		   int s = 1;
		   while(s < a.length ) {
			   mergepass(a, tmpa, s);
			   s=s*2;//有序的子列长度每次翻倍
			   mergepass(tmpa, a, s);   
			   //俩次的mergepass目的是最终让排列好的数值在a数组中
			   s=s*2;
		   }
		   
		   
	   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值