归并排序

  • 思想
          分治 ( 递归 ) 

          对集合一层层拆,拆到元素级开始比较左右两侧,在一层层合并,合并时因为子序列都有序,所以合并时按以此取子集合赋值给主集合位置即可
          
          归并排序
  • 算法图解
          定义first && last 简称 F 和 L
          first (F0)
          last (L9)
          mid=(first + last)/2=M4
          顺序拆分集合进行递归

          归并排序
  • 应用场景
          1T 的文件,取 Top K,拆分100M  10个, 分别内存快排,然后采用双路归并排序+多线程处理,每两路取TOP K  后在进一步归并,直到归并成一趟。
  • 算法优化(以不大幅度增加代码复杂度为原则)
          拆分合并时需要借助临时集合,所以多次申请内存空间,可以预先开辟固定大小集合,当小的时候在增大,调整增大策略
  • 平均时间复杂度(稳定)
          最差时间复杂度      О(n²)
          平均时间复杂度      O(nlogn)
  • 空间复杂度
          最差空间复杂度      О(n) total, O(1)

  • 代码演示(C#版本)
        public static void Sort(int[] array, int first, int last)
        {
            if (first < last)   //子表的长度大于1,则进入下面的递归处理
            {
                int mid = (first + last) / 2;   //子表划分的位置
               
                Sort(array, first, mid);   //对划分出来的左侧子表进行递归划分
               
                Sort(array, mid + 1, last);    //对划分出来的右侧子表进行递归划分
                MergeSortCore(array, first, mid, last); //对左右子表进行有序的整合(归并排序的核心部分)
                Console.WriteLine(string.Join(",", array));
            }
        }

        private static void MergeSortCore(int[] array, int first, int mid, int last)
        {
            //Console.WriteLine(string.Join(",", array));
            int indexA = first;             //左侧子表的起始位置
            int indexB = mid + 1;           //右侧子表的起始位置
            int[] temp = new int[last + 1]; //声明数组(暂存左右子表的所有有序数列):长度等于左右子表的长度之和。
            int tempIndex = 0;
            while (indexA <= mid && indexB <= last) //进行左右子表的遍历,如果其中有一个子表遍历完,则跳出循环
            {
                if (array[indexA] <= array[indexB]) //此时左子表的数 <= 右子表的数
                {
                    temp[tempIndex++] = array[indexA++];    //将左子表的数放入暂存数组中,遍历左子表下标++
                }
                else//此时左子表的数 > 右子表的数
                {
                    temp[tempIndex++] = array[indexB++];    //将右子表的数放入暂存数组中,遍历右子表下标++
                }
            }
            //有一侧子表遍历完后,跳出循环,将另外一侧子表剩下的数一次放入暂存数组中(有序)
            while (indexA <= mid)
            {
                temp[tempIndex++] = array[indexA++];
            }
            while (indexB <= last)
            {
                temp[tempIndex++] = array[indexB++];
            }

            //将暂存数组中有序的数列写入目标数组的制定位置,使进行归并的数组段有序
            tempIndex = 0;
            for (int i = first; i <= last; i++)
            {
                array[i] = temp[tempIndex++];
            }
        }