【算法】归并排序

基本概念:

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。

排序过程:

将序列分成 n 个有序的子序列,将相邻的有序子序列两两合并,并使合并后的序列内部有序,再对合并后的子序列重复进行上述过程,最后得到完全有序的序列。若将两个有序表合并成一个有序表,称为二路归并。

实例讲解:

有数组 R [ 10 ] = { 5 , 4 , 8 , 0 , 9 , 3,2 , 6,7 , 1 },另建立一个数组 R1 储存排序后的结果。

第一趟排序(颜色相同为一组序列):

5 , 4 

           8 , 0

                     9 , 3 

                               2 , 6 

                                         7 , 1

排序后结果:

4 , 5 , 0 , 8 , 3 , 9 , 2 , 6 , 1 , 7

第二趟排序(颜色相同为一组序列):

4 , 5 , 0 , 8 

                     3 , 9 , 2 , 6 

                                          1 , 7

排序后结果:

0 , 4 , 5 , 8 , 2 , 3 , 6 , 9 , 1 , 7

第三趟排序(颜色相同为一组序列):

0 , 4 , 5 , 8 , 2 , 3 , 6 , 9

                                          1 , 7

排序后结果:

0 , 2 , 3 , 4 , 5 , 6 , 8 , 9 , 1 , 7

第三趟排序(颜色相同为一组序列):

0 , 2 , 3 , 4 , 5 , 6 , 8 , 9 , 1 , 7

排序后结果:

0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

叁叁

代码实现:

实现归并排序之前,需要调用"一次归并“和”一趟归并“。

(1).一次归并:把首尾相接的两个有序表R[low...mid]、R[mid+1...high]归并成有序表R[low...high].

(2) .一趟归并:把一些相互连接的有序表依次两两归并成一些更大的有序表。

1.

一次归并代码如下:

// 一次归并排序 
void Merge(int low,int m,int high)         
{                
// 将两个有序的子序列 R [ low..m ] 和 R [ m+1..high ] 归并成一个有序的子序列 R
[ low..high ]     
// 置初始值       
   int i=low,j=m+1,k=0;               
   int *R1;           
// R1 是局部向量    
   R1=(int *)malloc((high-low+1)*sizeof(int));    
// 申请空间失败  
   if(!R1)                               
   {         
      puts("空间申请失败");        
      return;       
   }       
// 两子序列非空时取其小者输出到 R1 [ k ] 上   
   while(i<=m&&j<=high)                  
       R1[k++]=(R[i]<=R[j])?R[i++]:R[j++];      
// 若子序列非空,则复制剩余记录到 R1 中        
   while(i<=m)                           
       R1[k++]=R[i++];       
   while(j<=high)                      
       R1[k++]=R[j++];       
  // 归并完成后将结果复制回 R [ low..high ] 
   for(k=0,i=low;i<=high;k++,i++)         
       R[i]=R1[k];                 
}

2.

一趟归并代码如下:

// 一趟归并排序 
void mergepass(int n,int len) 
{
   int i,t;
   i=1;
   while(i<=n-2*len+1)
   {
       Merge(i,i+len-1,i+2*len-1);
       i=i+2*len;
   }
// 最后的序列长度小于 len
   if(i+len-1<n)  
      Merge(i,i+len-1,n);
}

归并排序算法的实现有非递归和递归两种实现方式。

3.

非递归方式实现:

void mergesort(int n) 
{
   int len;
   int *R1;            
// R1 是局部向量
   len=1;
   while(len<n)
   {
     mergepass(n,len);
     len=2*len;
      // 输出每趟排序的结果
     for(int i=1;i<=n;i++)   
         printf("%d ",R[i]); 
     printf("\n");
   }
}

4.

递归方式实现:

void MergeSortDC(int low,int high,int n) 
{                                     
//用分治法对R[low..high]进行二路归并排序        
  int mid;        
  if(low<high)         
  {                                
// 区间长度大于1          
    mid=(low+high)/2;                
//分解     
// 递归地对R[low..mid]排序
    MergeSortDC(low,mid,n);             
//递归地对R[mid+1..high]排序    
    MergeSortDC(mid+1,high,n);          
// 组合,将两个有序区归并为一个有序区          
    Merge(low,mid,high);                       
  }  
}

复杂度:

时间复杂度为 O(nlog₂n) 。这是该算法中最好、最坏和平均的时间性能。

空间复杂度为 O(n)。

比较操作的次数介于 (nlogn) / 2 和 nlogn - n + 1。

赋值操作的次数是 (2nlogn)。

归并排序比较占用内存,但却是一种效率高且稳定的算法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
归并排序是一种基于归并操作的有效排序算法,它采用分治法的思想。算法的基本思想是将已有序的子序列合并,得到完全有序的序列。在归并排序中,先将待排序序列通过二分法分为若干个有序子序列,然后再将这些子序列两两合并,直到最终得到完全有序的序列。归并排序通过牺牲空间来换取更高的时间效率。 以下是C语言实现归并排序的具体代码: ```c #include <stdio.h> // 合并两个有序数组 void merge(int arr[], int left, int mid, int right) { int i, j, k; int n1 = mid - left + 1; int n2 = right - mid; // 创建临时数组 int L[n1], R[n2]; // 将数据复制到临时数组中 for (i = 0; i < n1; i++) L[i] = arr[left + i]; for (j = 0; j < n2; j++) R[j] = arr[mid + 1 + j]; // 归并临时数组到原数组中 i = 0; j = 0; k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } // 复制剩余的元素 while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } // 归并排序 void mergeSort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; // 分 mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); // 治 merge(arr, left, mid, right); } } int main() { int arr[] = {12, 11, 13, 5, 6, 7}; int n = sizeof(arr) / sizeof(arr[0]); printf("排序前的数组: \n"); for (int i = 0; i < n; i++) printf("%d ", arr[i]); mergeSort(arr, 0, n - 1); printf("\n排序后的数组: \n"); for (int i = 0; i < n; i++) printf("%d ", arr[i]); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗星涌动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值