归并排序

12 篇文章 0 订阅

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

{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

明显快了很多。

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值