标签:算法
归并排序是另一种运用分治法排序算法。与快速排序一样,它依赖于元素之间的比较来排序。但是,归并排序需要额外的存储空间来完成排序过程。
同样可以用分治法的思想将排序分为三个步骤。
归并排序与其他排序最大的不同在于,它的归并过程。这个过程就是将两个有序的数据集合并成一个有序的数据集。正如我们看到的,合并两个有序数据集的过程是高效的,因为我们只需要遍历一次即可。
归并排序本质上是将无序元素分割成许多个包含一个元素的集,然后不断地将这些小集合合并,直到一个新的大有序数据集生成。
根据上图实现DEBUG DEMO如下:
import java.util.Arrays; /** * 归并排序 * * @author kevin LUAN * */ public class GBSortDemo { public static void main(String[] args) { Integer[] arrays = new Integer[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; Integer[] dest = new Integer[arrays.length]; mgSort(arrays, dest, 0, arrays.length); System.out.println("Sort result:"+Arrays.toString(dest)); } private static void mgSort(Integer[] arr, Integer[] dest, int low, int high) { System.out.println(Arrays.toString(arr)); int middle = getMiddle(low, high); if (high - low < 3) { copyData(arr, dest, low, high); return; } Integer[] left = new Integer[middle - low]; if (left.length > 1) { System.arraycopy(arr, low, left, 0, left.length); mgSort(left, dest, 0, left.length); } Integer[] right = new Integer[high - middle]; if (right.length > 0) { System.arraycopy(arr, middle, right, 0, right.length); mgSort(right, dest, 0, right.length); } } private static void sort(Integer[] left) { for (int i = 0; i < left.length; i++) { for (int j = i + 1; j < left.length; j++) { if (left[j] < left[i]) { left[j] = swap(left, i, left[j]); } } } } private static void copyData(Integer[] left, Integer[] dest, int low, int high) { sort(left); Integer start = 0; boolean isStart = false; for (int l = low; l < high; l++) { int val = left[l]; for (int i = 0 + start; i < dest.length; i++) { if (dest[i] == null) { dest[i] = val; break; } else if (dest[i] > val) { if (isStart == false) { start = i; } val = swap(dest, i, val); } } } } private static int swap(Integer[] dest, int i, int val) { try { return dest[i]; } finally { dest[i] = val; } } public static int getMiddle(int low, int high) { int total = high - low; if (total % 2 == 0) { return total / 2; } else { return total / 2 + 1; } } }
[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
[1, 3, 5, 7, 9]
[1, 3, 5]
[1, 3]
[5]
[7, 9]
[2, 4, 6, 8, 0]
[2, 4, 6]
[2, 4]
[6]
[8, 0]
Sort result:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
进一步优化,去掉System.arraycopy()代码如下:
import java.util.Random; /** * 归并排序 * * @author kevin * */ public class GBSort { public static Integer[] randomArray(int total) { Random random = new Random(); Integer[] arrays = new Integer[total]; for (int i = 0; i < total; i++) { arrays[i] = random.nextInt(10); } return arrays; } public static void main(String[] args) { Integer[] arrays = randomArray(10000); long start = System.currentTimeMillis(); arrays = sort(arrays); System.out.println("use time:" + (System.currentTimeMillis() - start)); } private static Integer[] sort(Integer[] arr) { Integer[] dest = new Integer[arr.length]; mgSort(arr, dest, 0, arr.length); return dest; } private static void mgSort(Integer[] arr, Integer[] dest, int low, int high) { int middle = getMiddle(low, high); if (high - low < 3) { copyData(arr, dest, low, high); return; } Integer left = middle - low; if (left > 1) { mgSort(arr, dest, low, low + left); } Integer right = high - middle; if (right > 0) { mgSort(arr, dest, middle, high); } } private static void sort(Integer[] left, int low, int high) { for (int i = low; i < high; i++) { for (int j = i + 1; j < high; j++) { if (left[j] < left[i]) { left[j] = swap(left, i, left[j]); } } } } /** * * @param left * @param dest * @param low * 低位下标 * @param high * 高位+1 */ private static void copyData(Integer[] src, Integer[] left, int low, int high) { if (high - low > 1) { sort(src, low, high); } int startIndex = 0; for (int l = low; l < high; l++) { int val = src[l]; for (int i = startIndex = calAddIndex(left, startIndex, low, val); i < high; i++) { if (left[i] == null) { left[i] = val; break; } else if (left[i] > val) { val = swap(left, i, val); } } } } public static int calAddIndex(Integer ascArray[], int startIndex, int endIndex, Integer val) { int start = startIndex; int end = endIndex - 1; int oldStart = -1; int oldEnd = -1; if (end == 0) { return 0; } while (true) { if (start == oldStart && end == oldEnd || end - start <= 1) { return start; } oldEnd = end; oldStart = start; int middleIndex = (end - start) / 2; if (ascArray[start + middleIndex] > val) {// 仍然大于改值需要向前继续二分查找 end = start + middleIndex; } else if (ascArray[start + middleIndex] < val) {// 小于该值需要往后继续二分查找 start = middleIndex + start; } else { return middleIndex + start; } } } private static int swap(Integer[] dest, int i, int val) { try { return dest[i]; } finally { dest[i] = val; } } public static int getMiddle(int low, int high) { int total = high - low; int middle; if (total % 2 == 0) { middle = total >>> 1; } else { middle = (total >>> 1) + 1; } if (low == 0) { return middle; } else { return middle + low; } } }
标签:算法
原文地址:http://blog.csdn.net/kevin_luan/article/details/37994837