和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
代码思路如下
import java.util.Arrays; public class MergeSort { public static void main(String[] args) { // int[] arr = {3,1}; // int[] arr = {1,3,5,2,4,6,8,10}; int[] arr = { 4, 7, 5, 3, 1, 9, 7, 0 }; System.out.println(Arrays.toString(arr)); // merge(arr, 0, 0, arr.length-1); mergeSort(arr, 0, arr.length-1); System.out.println(Arrays.toString(arr)); } //归并排序 public static void mergeSort(int[] arr,int low ,int high) { int middle = (low+high)/2; if (low<high) { //处理第一个数组 mergeSort(arr, low, middle); //处理第二个数组 mergeSort(arr, middle+1,high ); //归并 merge(arr, low, middle, high); } } //将两个分别排好序的数组,合并为一个排好序的数组 //其实传入了一个数组,用一个下标middle分为前后两部分 public static void merge(int[] arr,int low ,int middle ,int high) { //定义一个新的数组,存放归并排序后的数据(临时数组) int[] temp = new int[high-low+1]; //第一个数组中需要遍历的下标 int i = low; //第二个数组中需要遍历的下标 int j = middle+1; //temp数组的下标 int index = 0; //遍历两个数组,取出小的数字,放入temp数组中 while (i<=middle&&j<=high) { if (arr[i]<arr[j]) { temp[index] = arr[i]; i++; index++; }else { temp[index] = arr[j]; j++; index++; } } //当不满足while循环中的条件,也就是有一组数据数量少,已经排好序了 //只需要把数据多的那组剩下的数据按顺序放进temp数组中 while(i<=middle) { temp[index] = arr[i]; i++; index++; } while (j<=high) { temp[index] = arr[j]; j++; index++; } //最后,把排好序是temp中的数据存入原数组arr中 for (int k = 0; k < temp.length; k++) { arr[k+low]=temp[k]; } } }