实训三—分治算法专题—第8关:归并排序


任务描述

本关任务:编写一个能归并排序的小程序。

相关知识

归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序的步骤

例如数组A有11个数据,分别是: 49,38,65,97,76,13,27,74,89,8,2那么采用归并排序算法的操作过程如下图所示: 初始值 [49] [38] [65] [97] [76] [13] [27] [74] [89] [8] [2]   看成由长度为1的11个子序列组成   第一次合并之后 [38 49] [65 97] [13 76] [27 74] [8 89] [2]   看成由长度为1或2的6个子序列组成   第二次合并之后 [38 49 65 97] [13 27 74 76] [2 8 89]   看成由长度为4或3的3个子序列组成 第三次合并之后 [13 27 38 49 65 74 76 97] [2 8 89] 看成由长度为8或3的2个子序列组成 第四次合并之后[2 8 13 27 38 49 65 74 76 97 89]   合并算法的核心操作就是将一维数组中前后相邻的两个有序序列合并成一个有序序列。合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。合并算法的合并次数是一个非常重要的量,根据计算当数组中有3到4个元素时,合并次数是2次,当有5到8个元素时,合并次数是3次,当有9到16个元素时,合并次数是4次,按照这一规律,当有N个子序列时可以推断出合并的次数是X(2 >=N,符合此条件的最小那个X)。   其时间复杂度为:O(nlogn).所需辅助存储空间为:O(n)

编程要求

根据提示,在右侧编辑器补充代码,归并排序并输出排序前后的数组元素。

测试说明

平台会对你编写的代码进行测试:

测试输入: 10 预期输出: 95,8,78,25,18,77,75,71,47,7, (0,4,9) (0,2,4) (0,1,2) (0,0,1) (3,3,4) (5,7,9) (5,6,7) (5,5,6) (8,8,9) 7,8,18,25,47,71,75,77,78,95,

#include<iostream>  
using namespace std;  
#include <stdio.h>  
#include<stdlib.h>  
#include <time.h>  
#include <math.h>
void output(int *a,int n)  
{  
    int i;  
    for(i=0;i<n;i++)  
    {  
        printf("%d,",a[i]);  
    }  
    printf("\n");  
}
void swap(int &a, int &b)  
{  
    int t;  
    t=a;a=b;b=t;  
}
void Merge(int a[],int s,int m, int e)  
{ //将数组a的局部a[s,m]和a[m+1,e]合并到tmp,并保证tmp有序,然后再拷贝回a[s,e] //归并操作时间复杂度:O(e-m+1),即O(n)   
    int pb = 0;   
    int p1 = s,p2 = m+1;   
    int *tmp = new int[e-s+1];  
    /********** Begin **********/	
    while(p1<=m && p2<=e)
    {
        if(a[p1] <= a[p2])
            tmp[pb++] = a[p1++];
        else
            tmp[pb++] = a[p2++];
    }
    while(p1<=m)
        tmp[pb++] = a[p1++];
    while(p2<=e)
        tmp[pb++] = a[p2++];
    for(int i=0; i<e-s+1; i++)
        a[s+i] = tmp[i];
	/********** End **********/
    delete []tmp;  
}   
void MergeSort(int a[],int s,int e)  
{  
    int *tmp = new int[e-s+1];  
    if( s < e)   
    {    
        int m = s + (e-s)/2;   
        cout<<"("<<s<<","<<m<<","<<e<<")"<<endl;  
        /********** Begin **********/	
        MergeSort(a, s, m);
        MergeSort(a, m+1, e);
        Merge(a, s, m, e);
        /********** End **********/
    }  
    delete []tmp;  
 }
int main ()  
{   
    int i,n;
    int *a=0;  
    scanf("%d",&n);  
    srand(n);  
    a=new int[n];      
    for(i=0;i<n;i++)  
   {  
    a[i]=rand() % 100;  
   }  
    output(a,n);  
    MergeSort(a,0,n-1);  
    output(a,n);          
    delete []a;  
    return 0;  
}  

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值