常见排序算法总结——3、归并排序

常见排序方法

原创文章,转载请添加本网页链接
https://blog.csdn.net/qq_37334950/article/details/104388263

3、归并排序:将数组不断拆分,拆分为多个只包含单个元素的数组。再将数组不断有序合并,合并为一个有序的数组。

举例:
   原始数组:(28 12 1 8 23 32 6 19)
   第一次拆分:(28 12 1 8)(23 32 6 19)
   第二次拆分:(28 12)(1 8)(23 32)(6 19)
   第三次拆分:(28)(12)(1)(8)(23)(32)(6)(19)
   第一次合并:(12 28)(1 8)(23 32)(6 19)
   第二次合并:(1 8 12 28)(6 19 23 32)
   第三次合并:(1 6 8 12 19 23 28 32)

分析:进行log(2)(n)=log(2)(8)=3次的拆分后,拆分为n=8个单元素的数组。再进行3次的有序合并后,合并为8个元素的有序数组。

代码逻辑:因为拆分和合并都是相同的操作,所以只需要写一个拆分的函数,再写一个合并的函数,然后在拆分的函数中调用自己(自己调用自己,相当于我秀我自己,铁锅炖自己?)。拆分函数需要找到中间值,然后调用subList()函数进行拆分,最后return调用合并函数为最终结果即可。合并函数需要循环N次(N为两个需要合并数组的大小总和),每次取出两个数组中最小的元素,放入返还数组中。

代码示例(代码工具-AS):

public static void main(String args[]){
        ArrayList<Integer> list = new ArrayList<>();
        list.add(28);
        list.add(12);
        list.add(1);
        list.add(8);
        list.add(23);
        list.add(32);
        list.add(6);
        list.add(19);

        log(list,"默认数组:");//打印数组

        log(split(list),"最终结果为");//打印数组
    }
/**
     * 归并排序
     * @param list 需要排序的数组
     * @return 排序成功的数组
     */
    private static ArrayList<Integer> split(ArrayList<Integer> list){
        if (list.size() <= 1){//如果list只有一个元素或者小于一个元素,说明已经拆分到最后一步,可以直接返回list
            return list;
        }
        int i = list.size()/2;//取list大小一半的值,为了平均拆分list
        ArrayList<Integer> leftList = split(new ArrayList<>(list.subList(0,i)));//拆分后左侧的list
        ArrayList<Integer> rightList = split(new ArrayList<>(list.subList(i,list.size())));//拆分后右侧的list
        return merge(leftList,rightList);
    }
/**
     * 将两个有序数组有序合并为一个数组
     * @param leftList 第一个有序数组
     * @param rightList 第二个有序数组
     * @return 合并的数组
     */
    private static ArrayList<Integer> merge(ArrayList<Integer> leftList,ArrayList<Integer> rightList){
        int size = leftList.size() + rightList.size();//此为合并后数组的大小,也是下面循环的次数
        ArrayList<Integer> reList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            if (leftList.size() < 1){//如果leftList内没有元素,则将rightList所有元素直接加入到reList中,并结束循环
                reList.addAll(rightList);
                break;
            } else if (rightList.size() < 1){//如果rightList内没有元素,则将leftList所有元素直接加入到reList中,并结束循环
                reList.addAll(leftList);
                break;
            } else {//两个list中均有元素,则进行比较,将较小的加入到reList中
                if (leftList.get(0) > rightList.get(0)){
                    reList.add(rightList.get(0));
                    rightList.remove(0);
                } else {
                    reList.add(leftList.get(0));
                    leftList.remove(0);
                }
            }
        }
        return reList;
    }
/**
     * 打印数组
     * @param list 要打印的数组
     * @param string 打印前缀
     */
    private static void log(ArrayList<Integer> list,String string){
        String s = "";
        for (int m = 0; m < list.size(); m++) {
            if (m == 0){
                s = list.get(0)+"";
            } else {
                s = s + "," + (list.get(m)+"");
            }
        }
        if (string == null){
            System.out.println("--打印数组:" + s);
        } else {
            System.out.println(string + s);
        }
    }

结果一览
在这里插入图片描述
结果分析:归并排序要拆分至成N(N为数组元素个数)个单一元素的数组,再将这些单一数组有序合并成几次后合并为一个数组,无论数组的元素顺序,耗费的时间均相同

发布了3 篇原创文章 · 获赞 1 · 访问量 191

猜你喜欢

转载自blog.csdn.net/qq_37334950/article/details/104388263