归并排序

对于排序大列表数据,一个有效的排序算法是归并排序。类似于快速排序算法,其使用的是分治法来排序。归并排序的基本思想是:将两个或两个以上的有序子序列”归并”为一个有序序列。在内部排序中,通常采用的是2-路归并排序。即:将两个位置相邻的有序子序列“归并”为一个有序序列。

算法描述

归并操作的工作原理如下:  申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列   设定两个指针,最初位置分别为两个已经排序序列的起始位置   比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置   重复步骤3直到某一指针达到序列尾   将另一序列剩下的所有元素直接复制到合并序列尾

一、基本思想

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

      
    第一步,将列表中的11个元素看成11个有序的序列,每个子序列的长度为1,然后两两归并,得到5个长度为2和1个长度为1的有序子序列。
    第二步,将6个有序子序列两两归并,得到2个长度为4和1个长度为3的有序子序列。
    第三步,将2个长度为4的有序子序列归并,得到第三趟归并结果。
    第四步,将长度为8有序子序列和长度为3的有序子序列归并,得到第四趟归并结果,是长度为11的一个有序子序列。

二、并归排序的实现

复制代码
代码
     public   void  MergeSort(SeqList < int >  sqList)
    {
        
int  k  =   1 // 归并增量
         while  (k  <  sqList.GetLength())
        {
            Merge(sqList, k);
            k 
*=   2 ;
        }
    }
    
public   void  Merge(SeqList < int >  sqList,  int  len)
    {
        
int  m  =   0 // 临时顺序表的起始位置
         int  l1  =   0 // 第1个有序表的起始位置
         int  h1;  // 第1个有序表的结束位置
         int  l2;  // 第2个有序表的起始位置
         int  h2;  // 第2个有序表的结束位置
         int  i  =   0 ;
        
int  j  =   0 ;
        
// 临时表,用于临时将两个有序表合并为一个有序表
        SeqList < int >  tmp  =   new  SeqList < int > (sqList.GetLength());
        
// 归并处理
         while  (l1  +  len  <  sqList.GetLength())
        {
            l2 
=  l1  +  len;  // 第2个有序表的起始位置
            h1  =  l2  -   1 // 第1个有序表的结束位置
            
// 第2个有序表的结束位置
            h2  =  (l2  +  len  -   1   <  sqList.GetLength())  ?  l2  +  len  -   1  : sqList.Length  -   1 ;
            j 
=  l2;
            i 
=  l1;
            
// 两个有序表中的记录没有排序完
             while  ((i  <=  h1)  &&  (j  <=  h2))
            {
                
// 第1个有序表记录的关键码小于第2个有序表记录的关键码
                 if  (sqList.Data[i]  <=  sqList.Data[j])
                {
                    tmp.Data[m
++ =  sqList.Data[i ++ ];
                }
                
// 第2个有序表记录的关键码小于第1个有序表记录的关键码
                 else
                {
                    tmp.Data[m
++ =  sqList.Data[j ++ ];
                }
            }
            
// 第1个有序表中还有记录没有排序完
             while  (i  <=  h1)
            {
                tmp.Data[m
++ =  sqList.Data[i ++ ];
            }
            
// 第2个有序表中还有记录没有排序完
             while  (j  <=  h2)
            {
                tmp.Data[m
++ =  sqList.Data[j ++ ];
            }
            l1 
=  h2  +   1 ;
        }
        i 
=  l1;
        
// 原顺序表中还有记录没有排序完
         while  (i  <  sqList.GetLength())
        {
            tmp.Data[m
++ =  sqList.Data[i ++ ];
        }
        
// 临时顺序表中的记录复制到原顺序表,使原顺序表中的记录有序
         for  (i  =   0 ; i  <  sqList.GetLength();  ++ i)
        {
            sqList.Data[i] 
=  tmp.Data[i];
        }
    }
复制代码

三、时间复杂度分析

  二路归并排序的时间复杂度为O(nlog2n)。
  二路归并排序算法的空间复杂度为O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值