您的位置:首页 > 其它

排序系列之-归并排序

2014-05-12 17:31 197 查看
排序系列之-归并排序

花了一下午时间,终于搞懂了归并排序,好记性不如烂笔头,搞懂了还是记下来吧,以后留着看,以后还能给人推荐看,也省去不少麻烦。言归正传,讲讲今天的内容,归并排序。

归并排序它是建立在归并的基础上的一种排序算法。

1.那么首先必须了解什么是归并。

归并是两个有序数组a,b,把它们按照该顺序,组合在一起。即a,b都是从小到大排序,那么组合成的数组,也是按从小到大排序。该算法思路:

new一个临时数组tmp,拿a数组的第一个数字和b数组的第一个数字作比较,假如b数组的第一个数字比a数组第一个数字小,就取b[0],并且添加到tmp中,然后拿b[1]和a[0]作比较,也是取最小的,然后循环获取2个数组中对应位置的最小的数字,最
终,会把某一个数组全部取完,假设a全部取完,那么剩下的b数组中的肯定都比取完的这些数字大,那么就把这些剩下的数字按顺序直接加入到tmp末尾,则归并结束。

归并的 java代码如下:



/**
	 * 合并两个有序数组,返回合并后的数组
	 * @param a  有序数组a
	 * @param b  有序数组b
	 * @return   返回合并后的数组
	 */
	public static int[] merger(int[] a,int len1,int[] b,int len2){
//		int len1 =  a.length; //数组a的长度
//		int len2 = b.length; //数组b的长度
//		
		int[] re = new int[len1 + len2];
		int i = 0;  //遍历数组a的时候使用的游标
		int j = 0;  //遍历数组b的时候使用的游标
		int k = 0;  //添加到re数组中使用的游标
		while(i < len1 && j < len2){
			if(a[i] < b[j]){
				re[k++] = a[i++];
			}else{
				re[k++] = b[j++];
			}
		}
		while(i <len1){
			re[k++] = a[i++];
		}
		while(j < len2){
			re[k++] = b[j++];
		}
		return re;
	}
2.归并排序是采用分治的思想。讲数组对半分,一直分分分,分到只剩一个元素作为一个数组时,那么我们认为这个数组时有序的, 那么再回退,跟它的分下来的兄弟可以做归并,归并之后它还是有序的,在回退,一直会退到根数组(根数组时题目要排序的数组)的一半是,左边是有序的,右边是有序的, 继续合并,合并结束,源数组完成排序。下面看一幅图片,



从最上面的图片一直使用二分法,对其进行拆分,拆到每份只有一个元素师再逆向合并。

思想就是如此,下面看java代码:

/**
	 * 讲源数组拆分为有序的数组
	 * @param src  源数组
	 * @param i  源数组的起始位置
	 * @param j  源数组的结束为止
	 */
	public static void sort(int[] src,int i,int j){
		if(i < j){  //只要一段数组起始位置i小于结束位置j,则说明它长度>1,则继续拆分
			int mid = (i + j) / 2;
			sort(src,i,mid);  //对左边的数组段[i,mid]进行有序化
			sort(src,mid+1,j);  //对右边的数组段[mid+1,j]进行有序化
			mergerArray(src,i,mid,j); //合并两段有序数组
		}
	}
	/**
	 * 归并数组
	 * 两个数组分别为 数组的[s,mid],[mid+1,e]闭区间
	 * @param a 源数组
	 * @param s 源数组的起始位置
	 * @param mid 源数组的中间位置
	 * @param e  源数组的结束位置
	 */
	public static void mergerArray(int[] a,int s,int mid ,int e){
		if(s < e){  // 两个数组为两个数组时才归并
			int i = s;
			int j = mid + 1;
			//建立一个临时数组,长度为e-s+1
			int[] tmp = new int[e-s+1];
			int k = 0;//k用来指示临时数组的当前存放元素下标
			while(i <= mid && j <= e ){  //开始合并条件
				if(a[i] < a[j]){
					tmp[k++] = a[i++];
				}else{
					tmp[k++] = a[j++];
				}
			}
			/*将剩余的未合并的添加到临时数组末尾*/
			while(i <= mid){
				tmp[k++] = a[i++];
			}
			while(j <= e){
				tmp[k++] = a[j++];
			}
			//把临时数组复制会a[s,e]中
			System.arraycopy(tmp,0,a,s,e-s+1);
		}
	}


最后调用sort方法,拆分源数组,下标从0开始,到length-1

int[] a = new int[]{7,3,2,9,23,10,15,12}; //源数组
		sort(a,0,a.length-1); //对源数组进行排序


注释和讲解已经足够详细,相信大家都可以看懂了吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: