手把手教你写归并排序,Java实现

我是一个从汽车行业转行IT的项目经理,我是Edward。今天我们聊聊归并排序,merge sort是一个很有用的排序,无论是在Java的Arrays.sort算法还是针对对象的Collection.sort里都有应用,不过Collection.sort用到的是归并排序的优化版,Tim-sort。Tim-sort整体上是一种多路归并排序,用到了二分插入和优化归并,,但是细节方面有很多雕琢。

归并排序的写法分为三个步骤:

  • 1.首先特别设立一个左右两边等长且两边都有序的实验数组,写一个merge算法满足排序 建议:int[]arr= {1,3,4,8,9,2,5,6,7};
  • 2.将merge算法的各局部变量设置成函数的传入参数,增强算法的灵活性(但是注意截取的实验数组还是要两边等长且有序)
  • 建议:merge(arr,0,5,8);
  • 3.用递归思想完成sort内的算法
package algorithm;
/**
 * 归并排序:
 * 1.首先特别设立一个左右两边等长且两边都有序的实验数组,写一个merge算法满足排序
 * 2.将merge算法的各局部变量设置成函数的传入参数,增强算法的灵活性
 * (但是注意截取的实验数组还是要两边等长且有序)
 * 3.用递归思想完成sort内的算法
* @author EP
* @date 2020年4月8日  
* @version 1.0
 */

public class MergeSort {
	
	public static void main(String[] args) {

		int[]arr= {1,3,4,8,9,2,5,6,7};
		sort(arr,0,arr.length-1);
		print(arr);
	}
	
	public static void sort(int[]arr,int left,int right) {
		//1.设置递归的base case
		if (left==right) {
			return;
		}
		//2.分别排两边
		int mid = left+(right-left)/2;
		sort(arr,left,mid);
		sort(arr,mid+1,right);
		//3.合并
		merge(arr, left, mid+1,right);
		
		
		//merge(arr)
		//merge(arr,0,5,8);
	}
	static void merge(int[]arr,int leftPtr, int rightPtr, int rightBound) {
		int mid = rightPtr-1;
		int []temp = new int[rightBound-leftPtr+1];
		
		int i = leftPtr, j = rightPtr, k=0;
		while (i<=mid&&j<=rightBound) {
			temp[k++]= arr[i]<=arr[j] ? arr[i++]:arr[j++];
		}
		
		while (i<=mid) {
			temp[k++]=arr[i++];
		}
		while (j<=rightBound) {
			temp[k++]=arr[j++];
		}
		//不要忘了把temp数组复制到arr中
		for (int m = 0; m < temp.length; m++) {
			arr[leftPtr+m]=temp[m];
		}
	}
	
	static void print(int[]arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+" ");
		}	
	}

}

再用对数期验证一下:

package algorithm;


import java.util.Arrays;
import java.util.Random;
/**
 * 马士兵亲授
 * 验证算法——对数器
* @author EP
* @date 2020年4月3日  
* @version 1.0
 */

public class DataChecker {
	static int [] generateRandomArray() {
		Random r = new Random();
		int[]arr=new int[10000];
		for (int i = 0; i < arr.length; i++) {
			arr[i]=r.nextInt(10000);
		}
		return arr;
		
	}
	
	static void check() {
		int[]arr=generateRandomArray();
		int[]arr2=new int[arr.length];
		System.arraycopy(arr, 0, arr2, 0, arr.length);
		
		long start = System.currentTimeMillis();
		Arrays.sort(arr);
		long end = System.currentTimeMillis();
		System.out.println("Arrays.sort耗时:"+(end-start)+"ms");

		start = System.currentTimeMillis();
		MergeSort.sort(arr2, 0, arr2.length-1); 
		//ShellSortKnuth.sort(arr2);
		end = System.currentTimeMillis();
		System.out.println("Mysort耗时:"+(end-start)+"ms");
		
//		start = System.currentTimeMillis();       //希尔排序Knuth优化版的小测试
//		ShellSort.sort(arr);
//		end = System.currentTimeMillis();
//		System.out.println("sort耗时:"+(end-start)+"ms");
		
		boolean same = true;
		for (int i = 0; i < arr2.length; i++) {
			if (arr[i]!=arr2[i]) {
				same=false;
			}
		}
		System.out.println(same==true?"right":"wrong");
	
		
	}
	
	public static void main(String[] args) {
		check();
	}
}

结果是right,没有问题,而且速度还是相当快的,基本上跟Arrays.sort的速度相当。

原创文章 46 获赞 7 访问量 2078

猜你喜欢

转载自blog.csdn.net/EdwardWH/article/details/105395826