排序算法之归并排序算法优化

之前写了一篇介绍排序算法的排序算法之插入排序、希尔排序、归并排序(C#),发现计算数组的逆序对,我的算法速度比别人要慢很多倍。下面来分析一下为什么这两种归并算法会相差那么多。
第一种慢速归并算法,代码如下

		/// 
        /// 归并排序
        /// 
        /// 
        public int[] MergeSort(int[] array)
        {
     
            int length = array.Length;
            int half = length / 2;
            if (length <= 1)
            {
     
                return array;
            }
            //数组截取成左右两个
            int[] left = array.Take(half).ToArray();
            int[] right = array.Skip(half).ToArray();
            //递归 直至分成 左右两个只含一个元素时 排序后 向上返回
            left = MergeSort(left);
            right = MergeSort(right);
            return MergeSortDouble(left, right);
        }

        /// 
        /// 对两个数组排序后合并成一个返回
        /// 
        /// 
        /// 
        /// 
        public int[] MergeSortDouble(int[] left, int[] right)
        {
     
            List<int> li = new List<int>();
            int leftPositon = 0, rightPosition = 0;
            while (left.Count() > leftPositon && right.Count() > rightPosition)
            {
     
                if (left[leftPositon] > right[rightPosition])
                {
     
                    li.Add(right[rightPosition]);
                    rightPosition++;
                }
                else
                {
     
                    li.Add(left[leftPositon]);
                    leftPositon++;
                }
            }
            while (left.Count() > leftPositon)
            {
     
                li.Add(left[leftPositon]);
                leftPositon++;
            }
            while (right.Count() > rightPosition)
            {
     
                li.Add(right[rightPosition]);
                rightPosition++;
            }
            return li.ToArray();
        }

分析原因如下,代码使用了多次递归,每次递归均新建了多个数组进行执行。且存在数组和List的之间转换。较为浪费时间。

参考其他归并排序,对代码优化后如下。

		public static void sort(int[] arr)
        {
     
            int[] temp = new int[arr.Length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
            sort(arr, 0, arr.Length - 1, temp);
        }
        private static void sort(int[] arr, int left, int right, int[] temp)
        {
     
            if (left < right)
            {
     
                int mid = (left + right) / 2;
                sort(arr, left, mid, temp);//左边归并排序,使得左子序列有序
                sort(arr, mid + 1, right, temp);//右边归并排序,使得右子序列有序
                merge(arr, left, mid, right, temp);//将两个有序子数组合并操作
            }
        }
        private static void merge(int[] arr, int left, int mid, int right, int[] temp)
        {
     
            int i = left;//左序列指针
            int j = mid + 1;//右序列指针
            int t = 0;//临时数组指针
            while (i <= mid && j <= right)
            {
     
                if (arr[i] <= arr[j])
                {
     
                    temp[t++] = arr[i++];
                }
                else
                {
     
                    temp[t++] = arr[j++];
                }
            }
            while (i <= mid)
            {
     //将左边剩余元素填充进temp中
                temp[t++] = arr[i++];
            }
            while (j <= right)
            {
     //将右序列剩余元素填充进temp中
                temp[t++] = arr[j++];
            }
            t = 0;
            //将temp中的元素全部拷贝到原数组中
            while (left <= right)
            {
     
                arr[left++] = temp[t++];
            }
        }

总结,减少创建对象,减少装箱拆箱的转换以及其他类型转换,能不新增空间就不新增空间。

你可能感兴趣的:(排序算法,算法,排序算法,c#)