第三周作业——冒泡排序和归并排序

冒泡排序


用Java实现冒泡排序,代码如下:
	/**
	 * 冒泡排序:比较相邻的元素。如果第一个比第二个大,就交换他们两个。
	 * @param array 要排序的数组
	 * @return 排序号后的数组
	 */
	public static int[] BubbleSort(int[] array){
		if(array == null){
			throw new RuntimeException(" srcArray is null!");
		}
		
		int len = array.length;
		for(int i=0; i<len-1; i++){
			for(int j=0; j<len-i-1; j++){
				if( array[j] > array[j+1]){
					swap(array, j, j+1);
				}
			}
		}
		return array;
	}
	
	/**
	 * 交换数组指定位置的两个数
	 * @param src
	 * @param indexL
	 * @param indexR
	 */
	public static void swap(int[] src, int indexL, int indexR){
		src[indexL] = src[indexL] ^ src[indexR];
		src[indexR] = src[indexL] ^ src[indexR];
		src[indexL] = src[indexL] ^ src[indexR];
	}

测试数据:largeW.txt。由于信息量略大,故先选取前10,000和前100,000条数据进行测试,代码如下:
	public static void main(String[] args) throws FileNotFoundException {
		
		final String path = "C:\\sort";
		//数据源
		final String largeW = "largeW.txt";
		//目标文件
		final String largeW_bubble = "largeW_bubble.txt";
		//要排序的数的个数
		final int ARRAY_SIZE = 100000;
		int [] array = new int[ARRAY_SIZE];
		//开始时间
		long startTime = System.currentTimeMillis();
				
		Scanner sc = new Scanner(new File(path,largeW));  
    	PrintWriter pw = new PrintWriter(new File(path,largeW_bubble));  
    	
    	int index = 0;
    	//读取数据 -> 数组
    	while(index<ARRAY_SIZE){
    		array[index] = sc.nextInt();
    		index++;
    	}
		//冒一下泡
    	BubbleSort(array);    	
    	
    	//将排序后数组写到文件中
    	for(int num : array){
    		pw.println(num);
    	}
    	pw.flush();
    	pw.close();
    	sc.close();
    	 
    	//结束时间
    	long endTime = System.currentTimeMillis();
    	System.err.printf("冒泡排序结束,共耗时:%d毫秒, 数据量:%d ", endTime-startTime, ARRAY_SIZE); 
              
	}

运行结果:

数据量为10,000时,运行时间是1.666秒


数据量为100,000时,运行时间是75.063秒


数据量为1000,000时,运行时间是:2.33小时...



归并排序


用Java实现归并排序,代码如下:
	/**
	 * 归并排序
	 * @param src 要排序的数组
	 * @param des 排序后的数组
	 */
	public  MergeSort(int[] src, int[] des){
		//令初始化的子序列长度为1
		int len = 1, n=src.length-1;
		
		while( len<n){
			//当归并的趟数为奇数时,归并排序的结果存储在des数组
			MergerPass(src, des, n, len);
			len *= 2;
			
			//当归并的趟数为偶数时,归并排序的结果存储在src数组
			MergerPass(des, src, n, len);
			len *= 2;
		}		
	}
	
	/**
	 * 一趟归并
	 * @param src
	 * @param des
	 * @param n 待排序的数多少个
	 * @param len 子序列有多少个数
	 */
	public void MergerPass(int[] src, int[] des, int n, int len ){
		//从数组的第二个位置开始存放待排序列,方便计算位置
		int _p = 1;
		
		//相邻的两个有序序列长度均为len,执行一次归并后指针_p前进2*len
		while( _p <= (n-2*len+1) ){
			Merge(src, des, _p, _p+len-1, _p+2*len-1);
			_p += 2*len;
		}
		
		//相邻的两个有序序列长度分别为len和<len,执行一次归并后退出这趟归并
		if( _p < (n-len+1) ){
			Merge(src, des, _p, _p+len-1, n);
		}
		
		//只剩下一个子序列,将其copy到目标数组后退出这趟归并
		else{
			while(_p<=n){
				des[_p] = src[_p]; 
				_p++;
			}
		}
	}
	
	/**
	 * 一次归并
	 * @param src 待归并数组
	 * @param des 目标数组
	 * @param start 第一个个子序列的开始位置
	 * @param middle 第一个子序列的结束位置
	 * @param end 第二个子序列的结束位置
	 */
	public void Merge(int[] src, int[] des, int start, int middle, int end ){
		// i指向第一个个子序列的首,j指向第二个子序列的首,k指向目标数组的首
		int i = start, j = middle+1, k = start;
		
		//比较两个子序列的数大小,将较小的数存到目标数组对应位置
		while( i<=middle && j<=end ){
			if( src[i] <= src[j]){
				des[k++] = src[i++];						
			}else{
				des[k++] = src[j++];
			}
		}
		
		//收尾工作,将剩下的数全部存到目标数组
		if( i<=middle ){
			while( i<=middle ){
				des[k++] = src[i++];
			}
		}else{
			while( j<=end ){
				des[k++] = src[j++];
			}
		}
		
	}

测试数据: largeW.txt 。虽然信息量略大,但就算是1000,000条数据也秒排序!代码如下:
	public static void main(String[] args) throws FileNotFoundException {
		final String path = "C:\\sort";
		//数据源
		final String largeW = "largeW.txt";
		//目标文件
		final String largeW_merge = "largeW_merge.txt";
		//要排序的数的个数(注意!!! 第一个数不存放数据,为了方便计算。。。)
		final int ARRAY_SIZE = 1000000+1;
		int [] array = new int[ARRAY_SIZE];
		int[] des = new int[ARRAY_SIZE];
				
		Scanner sc = new Scanner(new File(path,largeW));  
    	PrintWriter pw = new PrintWriter(new File(path,largeW_merge));  
    	
    	//注意!!! 归并排序的数组的第一个位置没有存放数
    	int index = 1;
    	//读取数据 -> 数组
    	while(index<ARRAY_SIZE){
    		array[index] = sc.nextInt();
    		index++;
    	}
    	
    	//开始时间
    	long startTime = System.currentTimeMillis();
    	
		//归并排序
    	new MergeSort(array,des);    	
    	
    	
    	//结束时间
    	long endTime = System.currentTimeMillis();
    	System.err.printf("归并排序结束,共耗时:%d毫秒, 数据量:%d ", endTime-startTime, ARRAY_SIZE-1); 
    	
    	//将排序后数组写到文件中
    	for(int i=1; i<ARRAY_SIZE; i++){
    		pw.println(array[i]);
    	}
    	pw.flush();
    	pw.close();
    	sc.close();   	 
    	
	}



运行结果:

数据量为10,000时,运行时间是:0.056秒!


数据量为100,000时,运行时间是:0.082秒!!


数据量为1000,000时,运行时间是:0.583秒!!!




总结冒泡排序和归并排序


冒泡排序:

走第一趟时扫描 n-1 个数,第二趟时扫描 n-2 个数...
时间复杂度是: O(n) = (n-1+1)*(n-1)/2  --> O(n) = n^2

归并排序:

每走一趟扫描 n 个数, 共走 log2n趟。

时间复杂度是: O(n) = n * log2n


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值