归并排序

         基本思想:将两个或两个以上的有序子序列“归并”为一个有序子序列。在内部排序中,通常采用的是2-路归并排序,即将两个位置相邻的有序子序列“归并”为一个有序序列。类似于快排,其使用的也是分治的策略。

二路归并排序

         基本思想:将有n个记录的原始序列看做n个有序子序列,每个子序列的长度为1,然后从第1个子序列开始,把相邻的子序列两两合并,得到n/2个长度为21的子序列(当子序列的个数为奇数是,最后一组合并得到的序列长度为1),我们把这一过程称为一次归并排序,对一次归并排序的n/2个子序列采用上述方法继续顺序成成对归并,如此重复,当最后得到长度为n的一个子序列时,该子序列便是原始序列归并后的有序序列。

         过程如图所示:

排序 归并排序 分配排序_分配排序

第一趟:将列表中的11个元素看成11个有序的序列,每个子序列的长度为1,然后两两归并,得到5个长度为21个长度为1的有序子序列。

第二趟:将6个有序子序列两两合并,得到2个长度为41个长度为3的有序子序列。

第三趟:将2个长度为4的有序子序列归并,得到第3趟归并结果。

第四趟:将长度为8有序子序列和长度为3的有序子序列归并,得到第4趟归并结果,是长度为11的一个有序子序列。

时间复杂度:Onlog2n

代码实现:

                /// <summary>

        /// 归并排序

        /// </summary>

        /// <paramname="arr"></param>

        public static void mergeSort(ref int[]arr)

        {

            int k = 1;

            while (k < arr.Length)

            {

                arr=merge(arr, k);

                k *= 2;

            }

        }

        private static int[] merge(int[]arr,int len)

        {

            int m = 0;//临时顺序表的起始位置

            int l1 = 0;//第一个有序表的起始位置

            int h1;//第一个有序表的结束位置

            int h2,l2,i = 0,j = 0;

            int[] tarr = new int[arr.Length];

            //归并处理

            while (l1 + len < arr.Length)

            {

                l2 = l1 + len;//第二个有序序列的起始位置

                h1 = l2 - 1;//第一个序列的结束位置

                //第二个有序表的结束位置

                h2 = l2 + len - 1 <arr.Length ? l2 + len - 1 : arr.Length - 1;

                j = l2; i = l1;

                //两个有序表中的记录没有排序完

                while (i <= h1 && j<= h2)

                {

                    if (arr[i] <= arr[j])

                    {

                        tarr[m++] = arr[i++];

                    }

                    else

                    {

                        tarr[m++] = arr[j++];

                    }

                }

                //第一个有序表中还有记录没有排序完

                while (i <= h1)

                {

                    tarr[m++] = arr[i++];

                }

                //第二个有序表中还有记录没有排序完

                while (j <= h2)

                {

                    tarr[m++] = arr[j++];

                }

                l1 = h2 + 1;

            }

            i = l1;

            //原顺序表中还有记录没有排序完

            while (i < arr.Length)

            {

                tarr[m++] = arr[i++];

            }

            return tarr;

        }

分配排序

         分配排序的基本思想:排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序。他们的时间复杂度可达到线性阶:On

(1)      最高位优先法(MSD法):先按最主位关键码进行排序,分成不同的组,再按次主位关键码进行排序,进行细化,依次类推,然后将各个子序列连接起来,便得到一个有序序列。

(2)      最次位优先法(LSD法):与MSD方向相反。