归并排序(MergeSort)
2016-11-11 10:56
323 查看
1 归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法和快速排序都是采用分治法来设计算法的,区别在于归并排序把数组分为两个基本等长(最多相差一个元素)的子数组,分别排好序之后还要进行归并操作,而快速排序在拆分子数组的时候则有所不同,其取一个基准元素,拆分之后基准元素左边的元素都比基准元素小,右边的元素都不小于基准元素,这样只需要分别对两个子数组排序即可,不再像归并排序一样需要归并操作。归并排序是稳定的算法,其最坏的时间复杂度是O(n^2),其最好的时间复杂度是
O(nlogn).
2 归并过程
假设有数组 a,比较 a[i] 和 a[j] 的大小,若 a[i] ≤ a[j],则将第一个有序表中的元素 a[i] 复制到 r[k] 中,并令 i 和 k 分别加上 1;否则将第二个有序表中的元素 a[j] 复制到 r[k] 中,并令 j 和 k 分别加上 1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到 r 中从下标 k 到下标 t 的单元。归并排序的算法我们通常用递归实现,先把待排序区间 [s,t] 以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间 [s,t].3 归并举例
假设桌子上有两堆排好序(从小到大)的牌,每一次从两堆里面各抽取一张,比较一下两张的大小,如果两张一样大,都取出放到目标数组,否则取出较小的放到目标数组,另外一个放回原堆里面。接下来,重复上述过程,直到一堆扑克牌取完,再将另一堆扑克牌直接插入目标组即可。从上述描述中可知,归并排序需要额外的空间来存储临时数据。4 Java代码
public class MergeSort { public static void main(String[] args) { int[] arr = {3, 2, 1, 0, -1, -2, -3}; System.out.println("Before sort:"); printArray(arr); mergeSort(arr); System.out.println("After sort:"); printArray(arr); } public static void mergeSort(int[] arr) { sortarr(arr, 0, arr.length - 1); } private static void sortarr(int[] arr, int start, int end) { //将数组进行排序操作 if (start == end) { //单个元素直接返回 return; } int sortSize = end - start + 1; //计算数组总长度 int seperate; //设置分割元素 if (sortSize % 2 == 0) { seperate = start + sortSize / 2 - 1; } else { seperate = start + sortSize / 2; } sortarr(arr, start, seperate); sortarr(arr, seperate + 1, end); mergearr(arr, start, seperate, end); } private static void mergearr(int[] arr, int start, int seperate, int end) { //将数组进行归并操作 int totalSize = end - start + 1; int size1 = seperate - start + 1; int size2 = end - seperate; //分别创建与两个子组长度相等的数组 int[] arr1 = new int[size1]; int[] arr2 = new int[size2]; //分别将两个子组中的元素存储到新创建的两个数组中 for (int i = 0; i < size1; i++) { arr1[i] = arr[start + i]; } for (int i = 0; i < size2; i++) { arr2[i] = arr[seperate + 1 + i]; } int mergeCount = 0; int index1 = 0; int index2 = 0; while (mergeCount < totalSize) { // 先检查有没有其中的一个数组已经处理完 if (index1 == size1) { for (int i = index2; i < size2; i++) { arr[start + mergeCount] = arr2[i]; mergeCount++; index2++; } } else if (index2 == size2) { for (int i = index1; i < size1; i++) { arr[start + mergeCount] = arr1[i]; mergeCount++; index1++; } } else { //如果两个子组都没有处理完,则进行以下操作 int value1 = arr1[index1]; int value2 = arr2[index2]; if (value1 == value2) { arr[start + mergeCount] = value1; arr[start + mergeCount + 1] = value1; mergeCount += 2; index1++; index2++; } else if (value1 < value2) { arr[start + mergeCount] = value1; mergeCount++; index1++; } else if (value1 > value2) { arr[start + mergeCount] = value2; mergeCount++; index2++; } } } } public static void printArray(int[] arr) { //打印数组 System.out.print("{"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); if (i < arr.length - 1) { System.out.print(", "); } } System.out.println("}"); } }
相关文章推荐
- 1.7 逆序数与归并排序[inversion pairs by merge sort]
- 归并排序(Merge sort)
- 归并排序(merge-sort)
- 【从零学习经典算法系列】分治策略实例——归并排序(Mergesort)
- 合并排序(归并排序 MergeSort)
- 排序算法——归并排序(Merge Sort)
- Java排序算法--归并排序(MergeSort)
- 高级排序算法之-归并排序(MERGESORT)
- 【MergeSort】归并排序
- 链表和归并排序(Merge Sort)
- 归并排序(merge sort)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 归并排序(MergeSort)
- 归并排序(merge sort)
- 算法第三次作业(1. 排序。对文件 largeW.txt(下载链接)中的数据,编程实现冒泡排序(方法名:bubbleSort) 与 归并排序(mergeSort),把排序后的结果分别保存到largeW
- C:C的排序算法:归并排序(MergeSort)
- 归并排序(Merge Sort)递归、非递归 Java实现
- 归并排序(Merge Sort)
- 合并排序(归并排序 MergeSort)
- 常用排序算法—Merge Sort(归并排序)