思想:
假设初始序列右n个记录,首先将这n个记录看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2向上取整 个长度为2(n为奇数时,最后一个序列的长度为1)的有序子序列。在此基础上,在对长度为2的有序子序列进行两两归并,得到若干个长度为4的有序子序列。如此重复,直至得到一个长度为n的有序序列为止。
稳定性:稳定
时间复杂度计算:
- 数组的大小是2的幂,这样分下去始终可以被2整除。假设为2的k次方,即k=log2(n)。
- 每次我们选择的值刚好是中间值,这样,数组才可以被等分。
第一层递归,需要循环n次才能排序好,第二层循环2*(n/2)......
所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n
所以算法复杂度为O(log2(n)*n) 。
代码:
public static void sort(int[] data, int left, int right) { System.out.println(left+":"+right); if (left < right) { int center = (left + right) / 2; System.out.println(left+":"+center+":"+right); // 对左边数组进行递归 sort(data, left, center); System.out.println(left+":"+center+":"+right); // 对右边数组进行递归 sort(data, center + 1, right); // 合并 merge(data, left, center, right); } } public static void merge(int[] data, int left, int center, int right) { int[] tmpArr = new int[data.length]; int mid = center + 1; // third记录中间数组的索引 int third = left; int tmp = left; while (left <= center && mid <= right) { // 从两个数组中取出最小的放入中间数组 if (data[left] <= data[mid]) { tmpArr[third++] = data[left++]; } else { tmpArr[third++] = data[mid++]; } } // 剩余部分依次放入中间数组 while (mid <= right) { tmpArr[third++] = data[mid++]; } while (left <= center) { tmpArr[third++] = data[left++]; } // 将中间数组中的内容复制回原数组 while (tmp <= right) { data[tmp] = tmpArr[tmp++]; } System.out.println(Arrays.toString(data)); } public static void main(String[] args) { int[] a1 = {5,1,3,4,2}; sort(a1,0,a1.length-1); }
时间: 2024-10-07 06:30:20