继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

归并排序

刘信坚
关注TA
已关注
手记 52
粉丝 7795
获赞 665

归并排序其实是采用的是分治算法,也就是分而治之,比如一个数组:

{13,4,5,2,65,6},首先将这个数组分成{13,4,5},{2,65,6} ,然后继续分解{13,4} {5},{2,65},{6},最后{13},{4},{5},{2},{65},{6}

递归分解多个数组后就开始比较合并,首先是13跟4比较,再合并{4,13},然后合并的就是{4,5,13},接着{2,65},{2,6,65} ,最后{2,4,5,6,13,65} ,  就是分组合并,时间复杂度是o(nlogn) ,空间复杂度是o(n);也是一种稳定的排序,在代码实现上其实跟快速排序是差不多的,只不过快排是根据一个位置分成左边小于分界点,右边大于分界点。下面看代码:

	public static void MergeSort(int []a , int start , int end,int []temp) {		
		if(start < end) {			int mid = (start + end ) / 2;
			MergeSort(a,start,mid,temp);  //左边有序
			MergeSort(a,mid+1,end,temp);  //右边有序
			MergerArray(a,start,mid,end,temp); //合并
		}
		
	}	
	//合并2个数组
	public static void MergerArray(int []a,int start , int mid , int end , int []temp) {		
		int i = start , j = end ,m = mid+1;		int count = 0;		while(i <= mid && m <= j) {			if(a[i] < a[m]) {
				temp[count++] = a[i++];
			}else {
				temp[count++] = a[m++];
			}
		}		
		while(i <= mid) {
			temp[count++] = a[i++];
		}		
		while(m <= j) {
			temp[count++] = a[m++];
 		}		
		for(int k = start, s=0 ; k <= end ; k++) {
			a[k] = temp[s++];
		}
	}

下面测试下排序的速度:

	public static void main(String[] args) {
			
		 Instant start = Instant.now();
		 int a [] = new int [10000];
		 for(int i = 0 ; i < 10000 ; i++) {
			 a[i] = 10000 - i;
		 }
		 int temp[] = new int [10000];
		 MergeSort(a,0,10000-1,temp);
		 for (int i = 0 ; i < 10000 ; i ++) {
			System.out.println(a[i] +  " ");
		 }
		 Instant end = Instant.now();
		 System.out.println("归并排序所花费的时间 :   "+Duration.between(start, end).toMillis());
	}

10000个数字进行逆序排列,对比快排:

....
9993 
9994 
9995 
9996 
9997 
9998 
9999 
10000 
归并排序所花费的时间 :   147

下面是快速排序:

public static void QuickSorted(int a[], int start , int end) {
		if(start < end) {
			int mid = Partition(a,start,end);
			QuickSorted(a, start , mid-1);
			QuickSorted(a, mid+1 , end);
		}
	}
   	
	
	private static int Partition(int[] a, int start, int end) {
		int i = start , j = end;
		int temp = a[start];
		while(i < j ) {
			while(i < j && a[j] >= temp) {
				j--;
			}
			a[i] = a[j];
			
			while(i < j && a[i] <= temp) {
				i++;
			}
			a[j] = a[i];
			
		}
		a[i] = temp;
		return i;
	}

	public static void main(String[] args) {
		
		
		 Instant start = Instant.now();
		 int a [] = new int [10000];
		 for(int i = 0 ; i < 10000 ; i++) {
			 a[i] = 10000 - i;
		 }
		 QuickSorted(a,0,10000-1);
		 for (int i = 0 ; i < 10000 ; i ++) {
			System.out.println(a[i] +  " ");
		 }
		 Instant end = Instant.now();
		 System.out.println("快速排序所花费的时间 :   "+Duration.between(start, end).toMillis());

}		
		
		

....
9992 
9993 
9994 
9995 
9996 
9997 
9998 
9999 
10000 
快速排序所花费的时间 :   193

快速排序和堆排序都是o(nlogn)的排序,下面在对比下o(n*n)的 排序,下面就以冒泡排序为例:

	private static void BubbleSorted(int[] a) {
		 for(int i = 0 ; i < a.length - 1 ; i ++) {
			 for(int j = 0 ; j < a.length - 1 - i ; j++) {
				 if(a[j] > a[j+1]) {
					 int temp = a[j];
					 a[j] = a[j+1];
					 a[j+1] = temp;
				 }
			 }
		 }
	}

 public static void main(String []args){		
         Instant start = Instant.now();
		 int a [] = new int [100000];
		 for(int i = 0 ; i < 100000 ; i++) {
			 a[i] = 100000 - i;
		 }
		 BubbleSorted(a);
		 for (int i = 0 ; i < 100000 ; i ++) {
			System.out.println(a[i] +  " ");
		 }
		 Instant end = Instant.now();
		 System.out.println("冒泡排序所花费的时间 :   "+Duration.between(start, end).toMillis());

}

测试10万个数据:

		    99993 
			99994 
			99995 
			99996 
			99997 
			99998 
			99999 
			100000 
			冒泡排序所花费的时间 :   4417

堆排序测试10万个数据:

99992 
			99993 
			99994 
			99995 
			99996 
			99997 
			99998 
			99999 
			100000 
			归并排序所花费的时间 :   953

明显快了很多。







打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP