zoukankan      html  css  js  c++  java
  • 归并排序

    归并排序是冒泡排序的优化算法,它采用了分治法的思想,使用递归将其解决,以数组{0,3,2,9,6}为例
    分治法的基本思想:将一个大问题分割成若干个类似的小问题,解决完小问题后再将小问题组合大问题
    分:用递归法 取mid=(left+right)/2 先递归左子表再递归右子表 当left>=right时 分割结束
    {0,3,2,9,6} left=0,ring=4,mid=2
    第一轮分割;
    {0,3,2}left=0,right=2,mid=1 {9,6}left=3,right=4,mid=3
    第二轮分割:
    {0,3}left=0,right=1,mid=1 {2}left=right=2不可继续分割 {9}left=right=3不可继续分割 {6}left=right=4不可继续分割
    第三轮分割:
    {0}left=right=0不可继续分割 {3}left=right=1不可继续分割 {2}left=right=2不可继续分割 {9}left=right=3不可继续分割 {6}left=right=4不可继续分割
    分割完毕 开始合并
    第三轮合并到第二轮:{0}{3}=>{0,3}
    第二轮合并到到第一轮:{0,3}{2}=>{0,2,3} {9,6}=>{6,9}
    第二轮(此时只有两个数组)合并:{0,2,3,6,9}
    在合并过程中关键:除了最后一轮合并,每次合并过程处理的都是小数组(即分割过程中的数组) 该数组长度为right-left+1
    合并过程:设置左右两个指针,依次遍历左子表和右子表(l<=mid&&r<=right)相应元素的大小,如arr[l]<arr[r]则把arr[l]放进temp中 反之亦然
    如果跳出循环还有一边子表没有遍历完 则将改子表剩余元素全部放入temp中(这么做的是因为两边子表都是有序的)
    完成以上步骤 再将temp中元素全部拷贝到arr中 除了最后一次是拷贝全部元素,其他时候都是拷贝right-left+1(即处理完的有序段长度)
    归并排要额外开一个数组用来保存数据 是空间换时间的算法
    完整代码如下:

            public static void meregeSort(int[] arr, int left, int right, int[] temp)
            {
    
                if (left < right)
                {
                    int mid = (left + right) / 2;
                    //递归左子表
                    meregeSort(arr, left, mid, temp);
                    //递归右子表
                    meregeSort(arr, mid + 1, right, temp);
                    //合并
                    merege(arr, left, right, temp);
                }
            } 
            public static void merege(int[] arr, int left, int right, int[] temp)
            {
                int mid = (left + right) / 2;//以mid为界限两边子表开始比较
                int l = left;//左侧子表开始
                int r = mid + 1;//右侧子表开始
                int t = 0;//temp索引
                while (l <= mid && r <= right)
                {
                    if (arr[l] < arr[r])//如果arr[l]<arr[r] 则把arr[l]存到temp中 同时r++
                    {
                        temp[t++] = arr[l++];
                    }
                    else//如果arr[l] > arr[r] 则把arr[r]存到temp中 同时r++
                    {
                        temp[t++] = arr[r++];
                    }
                }
    
                //如果两边子表还有一边没用遍历完 则将没遍历完的子表全部放入temp中(这么做的前提是因为两边子表都是有序的了
                //左子表没用遍历完
                while (l <= mid)
                {
                    temp[t++] = arr[l++];
                }
                //右子表没用遍历完
                while (r <= right)
                {
                    temp[t++] = arr[r++];
                }
                //将temp中的数据拷贝到arr中 除了最后一次合并 每次合并都不是拷贝全部数据 而是right-left+1个数据(即传进来的分数组长度)
                t = 0;
                while (left <= right)
                {
                    arr[left++] = temp[t++];
                }
            }
  • 相关阅读:
    李超线段树 (Li-Chao Segment Tree)
    NowCoder Contest 894
    AtCoder Beginning Contest 126
    华工软院IBM LinuxONE Community Cloud云计算实验文档
    Codeforces Round #561 (div. 2)
    Comet OJ Contest #3
    Codeforces Edu Round 65 (Rated for Div. 2)
    莫队算法 (Mo's Algorithm)
    Codeforces Round #559 (Div. 2)
    GDCPC2019 广东省赛总结
  • 原文地址:https://www.cnblogs.com/TheLin/p/13887414.html
Copyright © 2011-2022 走看看