排序算法-归并排序

归并排序:只能对两段有序的数组进行归并,归并从更大的有序数组

 归并时需要两个下标,分别是指向首部的i,以及指向mid+1的j。

 初始化过后,对i和j的元素进行比较,小的放入temp之中。

j<1,将元素1放入temp,k++.j++

在对i和j进行比较,以此往复

 当j>r时,直接将剩余部分放到temp中

 然后将temp拷贝到arr中

对于中间下标 int mid = (r+l)/2;当r、l两个都为比较大的值时,可能r+l会造成容量溢出超过了int的值范围。因此 使用int mid = l+(r-l)/2;

 class MergeSort1
    {
        public static void Sort(int[] arr)
        {
            int n = arr.Length;
            int[] temp = new int[n];
            Sort(arr, temp, 0, n - 1);
        }

        private static void Sort(int[] arr,int[] temp,int l,int r)
        {
            //int mid = (r + l) / 2;
            int mid = l + (r - l) / 2;
            Merge(arr, temp, l, mid, r);
        }

        // 将arr[l...mid]和arr[mid+1...r]两部分有序排列进行归并
        private static void Merge(int[] arr,int[] temp,int l,int mid ,int r)
        {
            int i = l;
            int j = mid + 1;
            int k = l;

            //左右半边都有元素(将小的放到temp数组中)
            while(i<=mid && j <= r)
            {
                if(arr[i] < arr[j])
                    temp[k++] = arr[i++];
                else //arr[i] >= arr[j]
                    temp[k++] = arr[j++];
            }

            //左半边还有元素,右半边用尽(取左半边的元素)
            while (i <= mid)
                temp[k++] = arr[i++];

            //右半边还有元素,左半边用尽(取右半边的元素)
            while (j <= r)
                temp[k++] = arr[j++];

            //将temp数组拷贝回给arr数组,完成arr排序
            for (int z = l; z <= r; z++)
                arr[z] = temp[z];

        }
    }

 保证左右有序

 递归分割

对数组的中间进行分割,变成两个数组,在对两个数组的中间进行分割

                                                       6  3  2  8   1  7 5 7

                                                        6 3 2 8  | 1 7 5 4

                                                      6 3 |  2 8 |  1 7 | 5  4

                                                    6 | 3 | 2 | 8 | 1 | 7 | 5 | 4

然后现在都变成了一个个单独的数组,进行比较:

                                                    3 6 | 2 8 | 1 7 | 4 5 |    

                                                     2 3 6 8 | 1 4 5 7    

                                                    1 2 3 4 5 6 7 8  完成排序    

代码递归实现:

首先我们需要将一整个数组一直递归分割,分成一个个的单个数组。

上面代码中 Sort函数可以进行分割,仅分割一次

private static void Sort(int[] arr,int[] temp,int l,int r)
        {
            //int mid = (r + l) / 2;
            int mid = l + (r - l) / 2;
            Merge(arr, temp, l, mid, r);//排序
        }

我们在Sort里调用Sort自己就可以递归调用

什么时候结束递归呢?当l=>r的时候数组中就只有一个元素了那时进行返回。

调用Merge()进行排序,例如 6 3 2 8变成3 6 2 8。在调用上一层的Merge() 2 3 6 8 

private static void Sort(int[] arr,int[] temp,int l,int r)
        {  
            if (l >= r) return;
            int mid = l + (r - l) / 2;
            //Console.WriteLine("mid = {0}", mid);

            Sort(arr, temp, l, mid);        //将左半边排序
            Sort(arr, temp, mid + 1, r);    //将右半边排序
            Merge(arr, temp, l, mid, r);    //归并结果
        }

过程如下:

 当Sort(0,0)时,l=r 因此返回。执行Sort(arr,temp,mid+1,r)。也就是Sort(0,1)下的Sort(1,1),同理因为1=1,l=r。return。执行Merge(arr,temp,0,0,1)也就是 5 4排序后int[ ] arr ={4,5,3,2,1};

Sort(0,1)执行完毕

 执行Sort(0,2)下的Sort(arr,tem,mid+l,r),Sort(2,2)返回执行Merge(arr,temp,0,1,2)

int[ ] arr ={4,5,3,2,1};变成{3,4,5,2,1}

时间复杂度

 一组无序数组:归并排序与插入排序比较:

 可以看出归并比插入快很多。O(nlgn)比O(n2)快很多

一组几乎有序的数组

 归并慢了一些,但也没慢多少。O(nlgn)慢于O(n)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值