本文共 2122 字,大约阅读时间需要 7 分钟。
归并排序(Merging Sort)是与插入排序、交换排序、选择排序不同的另一类排序方法。归并的含义时将两个(二路归并)或两个以上(多路归并)的有序表合并成一个新的有序表。此处只讨论二路归并。
基本思想
将待排序序列r[0]到r[n-1]看成是一个含有n个长度为1的有序子表,将这些子表进行两两归并,得到[n/2]个子表;然后再将这[n/2]个子表进行两两归并,直到最后得到一个长度为n的有序表为止。
性能分析
空间复杂度:需要一个与待排序序列登场的辅助数组来存放排序过程中的中间结果,所以空间复杂度为 O(n) 。
时间复杂度:最好最坏和平均的时间复杂度均为 O(nlogn) 。
稳定性:是稳定的。
java实现代码:
/** * 归并排序: O(nlogn) * 递归实现:合并两个已经排序的表(一个数组存储) * @param iniArr 原始数组(包含两个已经排序的表) * @param resArr 排序数组 * @param left 最左索引 * @param right 最优索引 */ public static> void mergeSort(T[] iniArr, T[] resArr, int left, int right) { if(left < right) { int center = (right + left) / 2; mergeSort(iniArr, resArr, left, center); mergeSort(iniArr, resArr, center + 1, right); // 注意center+1 merge(iniArr, resArr, left, center + 1, right); } } /** * 合并归并排序的结果 * @param iniArr 原始数组 * @param resArr 排序数组 * @param leftPos 左边起点索引 * @param rightPos 右边起点索引 * @param rightEnd 右边结束索引 */ public static > void merge(T[] iniArr, T[] resArr, int leftPos, int rightPos, int rightEnd) { int leftEnd = rightPos - 1; // 左序列结束索引 int nElements = rightEnd - leftPos + 1; // 序列中元素数目 int tmpPos = leftPos; // resArr数组索引 // 左右序列比较排序 while(leftPos <= leftEnd && rightPos <= rightEnd) { if (iniArr[leftPos].compareTo(iniArr[rightPos]) <= 0) { resArr[tmpPos++] = iniArr[leftPos++]; } else { resArr[tmpPos++] = iniArr[rightPos++]; } } // 最后一次比较后,拷贝所有剩余的左边元素 while(leftPos <= leftEnd) { resArr[tmpPos++] = iniArr[leftPos++]; } // 最后一次比较后,拷贝所有剩余的右边元素 while(rightPos <= rightEnd) { resArr[tmpPos++] = iniArr[rightPos++]; } // 将结果数组替换原数组,参与后续递归的归并排序 // 最后的结果iniArr和resArr数组都已经经过了排序,完全一致 for (int i = 0; i < nElements; i++) { iniArr[rightEnd] = resArr[rightEnd]; rightEnd--; } }
参考:
1. 刘小晶,数据结构——Java语言描述(第2版),清华大学出版社 2. MARK A W, 数据结构与算法分析: Java 语言描述,机械工业出版社