归并排序-迭代实现-java

简洁代码

public class ZZ {
    public static void main(String[] args) {
        int[] arr = {3, 4, 2, 5, 7, 0, 9, 8, 11, 1, 6};
        mergeSort(arr);
    }
    public static void mergeSort(int[] arr) {
        int len = arr.length;
        int k = 1;
        while (k < len) {
            MergePass(arr, k, len);
            k *= 2;
        }
    }
    private static void MergePass(int[] arr, int k, int len) {
        int i = 0;
        while (i + 2 * k - 1 < len) {
            merge(arr, i, i + k - 1, i + 2 * k - 1);
            i += 2 * k;
        }
        if (i + k - 1 < len - 1) {
            merge(arr, i, i + k - 1, len - 1);
        }
    }
    private static void merge(int[] arr, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        int i = low;
        int j = mid + 1;
        int k = 0;
        for (; i <= mid && j <= high; k++) {
            if (arr[i] < arr[j]) {
                temp[k] = arr[i++];
            } else {
                temp[k] = arr[j++];
            }
        }
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= high) {
            temp[k++] = arr[j++];
        }
        for (int l = 0; l < temp.length; l++)
            arr[low + l] = temp[l];
    }
}

啰嗦的注释版本

public class ZZ {
    public static void main(String[] args) {
        int[] arr = {3, 4, 2, 5, 7, 0, 9, 8, 11, 1,6};
        mergeSort(arr);
//        printArr(arr);
    }

    public static void mergeSort(int[] arr) {
        //使用非递归的方式来实现归并排序
        int len = arr.length;
        int k = 1;//为什么要从1开始?一开始对长度为1的序列进行两两合并
        while (k < len) {
            MergePass(arr, k, len);
            k *= 2;
        }
    }
    //MergePass方法负责将数组中的相邻的有k个元素的字序列进行归并
    private static void MergePass(int[] arr, int k, int len) {
        int i = 0;
        /**
         * 为什么要设置为i < len - 2 * k + 1 ?其实这样子写是很容易误导读者的.因为会纠结i的取值范围
         *
         * 但是写成(i + 2 * k - 1 < len),就会把(i+2*k-1)当做一个整体看待
         */
        //从前往后,将2个长度为k的子序列合并为1个。对于序列{3, 4, 2, 5, 7, 0, 9, 8, 1, 6},当k=8的时候,因为i>(len-2*k+1),所以根本没有进入while循环
        while (i + 2 * k - 1 < len) {//无论什么时候都是从第一个数开始的。因为i=0
            merge(arr, i, i + k - 1, i + 2 * k - 1);
            i += 2 * k;
        }
        //测试代码
        System.out.print("1:k=" + k + " ");
        printArr(arr);
        //这段代码保证了,将那些“落单的”长度不足两两merge的部分和前面merge起来。(连接起来之前也是要进行排序的,因此有了下面的merge操作)
        //当k=2,剩下(11,1,6),因为长度不满足两两merge,所以排序变为(1,6,11)
        //当k=4,剩下(11,1,6),不是长度两两,这里只是一个长度,因此没有必要进行连接
        /**
         *  不要写成 i+k-1 <= len -1 ,因为可能会进行一次无谓的排序。
         *  随便举个例子。如果,当k=2,(3,4)(2,5)(0,7)(8,9)(1,11)。 i+k-1=9 len-1=9.  此刻根本没有必要进行merge。因为在k=1的时候就已经将(1,11)进行排序
         * 
         * */
        if (i+k-1 < len - 1) {//从数组下标的角度去看待。
            System.out.println("需要连接落单的数据 k="+k);
            merge(arr, i, i + k - 1, len - 1);
        }
        //测试代码
        System.out.print("2: k=" + k + " ");
        printArr(arr);
    }
    //merge函数实际上是将两个有序数组合并成一个有序数组
    //因为数组有序,合并很简单,只要维护几个指针就可以了
    private static void merge(int[] arr, int low, int mid, int high) {
        //temp数组用于暂存合并的结果
        int[] temp = new int[high - low + 1];
        //左半边的指针
        int i = low;
        //右半边的指针
        int j = mid + 1;
        //合并后数组的指针
        int k = 0;
        //将记录由小到大地放进temp数组
        for (; i <= mid && j <= high; k++) {
            if (arr[i] < arr[j]) {
                temp[k] = arr[i++];
            } else {
                temp[k] = arr[j++];
            }
        }
        //接下来两个while循环是为了将剩余的(比另一边多出来的个数)放到temp数组中
        while (i <= mid) {
            temp[k++] = arr[i++];
        }
        while (j <= high) {
            temp[k++] = arr[j++];
        }
        //将temp数组中的元素写入到待排数组中
        for (int l = 0; l < temp.length; l++)
            arr[low + l] = temp[l];
    }
    public static void printArr(int[] arr) {
        System.out.print("排序结果为: ");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页