《归并排序》——Java实现
这次的代码是在一篇博客找到的,忘记是哪个了,所以原主人希望指出转载的话,请联系。
归并排序是用了分治的思想,就是将大问题不断拆分成与原问题相同但是规模更小的问题,当将每个小问题都解决后,大问题自然就解决了。
在排序中,是将数组拆成两部分,然后将这两个部分继续拆分,直到拆成一个,因为一个元素默认就是有序的了,然后开始合并,两两合并,合并的时候两组排序,最后就是合并成功,数组有序。
平均时间复杂度是O(n log n),不过这个需要额外的空间作中转,所以还有空间复杂度是O(n)。
1 public class MergeSort implements IArraySort{ 2 3 @Override 4 public int[] sort(int[] arr) { 5 // 复制数组,不对入参修改 6 int[] newArr = Arrays.copyOf(arr, arr.length); 7 8 int[] t = new int[newArr.length]; 9 mergeSort(newArr,0,newArr.length-1,t); 10 return newArr; 11 } 12 13 //分+合方法 14 public void mergeSort(int[] arr, int left, int right, int[] temp) { 15 if(left < right) { 16 int mid = (left + right) / 2; //中间索引 17 //向左递归进行分解 18 mergeSort(arr, left, mid, temp); 19 //向右递归进行分解 20 mergeSort(arr, mid + 1, right, temp); 21 //合并 22 merge(arr, left, mid, right, temp); 23 24 } 25 } 26 27 //合并的方法 28 /** 29 * 30 * @param arr 排序的原始数组 31 * @param left 左边有序序列的初始索引 32 * @param mid 中间索引 33 * @param right 右边索引 34 * @param temp 做中转的数组 35 */ 36 public void merge(int[] arr, int left, int mid, int right, int[] temp) { 37 38 int i = left; // 初始化i, 左边有序序列的初始索引 39 int j = mid + 1; //初始化j, 右边有序序列的初始索引 40 int t = 0; // 指向temp数组的当前索引 41 42 //(一) 43 //先把左右两边(有序)的数据按照规则填充到temp数组 44 //直到左右两边的有序序列,有一边处理完毕为止 45 while (i <= mid && j <= right) {//继续 46 //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素 47 //即将左边的当前元素,填充到 temp数组 48 //然后 t++, i++ 49 if(arr[i] <= arr[j]) { 50 temp[t] = arr[i]; 51 t += 1; 52 i += 1; 53 } else { //反之,将右边有序序列的当前元素,填充到temp数组 54 temp[t] = arr[j]; 55 t += 1; 56 j += 1; 57 } 58 } 59 60 //(二) 61 //把有剩余数据的一边的数据依次全部填充到temp 62 while( i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temp 63 temp[t] = arr[i]; 64 t += 1; 65 i += 1; 66 } 67 68 while( j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temp 69 temp[t] = arr[j]; 70 t += 1; 71 j += 1; 72 } 73 74 75 //(三) 76 //将temp数组的元素拷贝到arr 77 //注意,并不是每次都拷贝所有 78 t = 0; 79 int tempLeft = left; 82 while(tempLeft <= right) { 83 arr[tempLeft] = temp[t]; 84 t += 1; 85 tempLeft += 1; 86 } 87 88 } 89 }

浙公网安备 33010602011771号