基本思想:
1)首先需要一个临时空间temp用来存放合并后的元素,长度为排列好的元素总个数。
2)取两个指针,分别为左右部分数组的头元素。
3)比较指针指向元素,将较小(较大)的那个放入temp(注意相等时不做元素位置交换),并将两指针向后移动一个step。
4)循环步骤3直到其中一段数组没有剩余元素(其中一段被遍历完)。
5)将还有元素剩余的另外一半数组元素直接放入temp尾部
代码实现:
public static void merge(int[] list, int left, int mid, int right) { int len = right - left + 1; int[] temp = new int[len]; //辅助空间O(n) int l = left; int r = mid + 1; int index = 0; while (l <= mid && r <= right) { temp[index++] = (list[l] <= list[r] ? list[l++] : list[r++]); // 带等号保证归并排序的稳定性 } while (l <= mid) { temp[index++] = list[l++]; } while (r <= right) { temp[index++] = list[r++]; } System.arraycopy(temp, 0, list, left, len); } //递归 public static void recSort(int[] list, int left, int right) { if (left < right) { int mid = (left + right) / 2; recSort(list, left, mid); recSort(list, mid + 1, right); merge(list, left, mid, right); } } //非递归 public static void nonRecSort(int[] list, int len) { int left, mid, right; for (int i = 1; i < len; i *= 2) //初始以1个元素为单位,每轮操作元素数翻倍 { left = 0; while (left + i < len) // 后半段仍有元素剩余 { mid = left + i - 1; right = mid + i < len ? mid + i : len - 1;// 确定后半段尾部位置 merge(list, left, mid, right); left = right + 1; } }
时间复杂度:
最优情况:O(nlogn)
最差情况:O(nlogn)
平均:O(nlogn)
空间复杂度:
O(n)
稳定性:
稳定
时间: 2024-12-25 07:40:01