分治法实现合并排序

实验目的
分治法实现合并排序,得到不同规模数据实验的时间对比,并进行时间复杂度分析。

实验原理
使用分治法,根据不同的输入用例n,准确输出这n个随机数从小到大排列后的序列。
合并排序算法思想:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。

实验步骤
①创建两个数组。
②不断将原数组从中间分开,然后放入两个数组中。
③将两个数组中的元素逐一进行比较放入原数组中。

关键代码

//合并函数,q为切分点,array数组就是随机数的数组 
void Merge(int *_Array, int p, int q, int r) 
{//p:第0个;r:第n-1个数,q:第(r + p)/2个数
    int len1=q-p+1;
    int len2=r-q;
    int *L=new int[len1+1];//用动态数组储存左边的数
    int *R=new int[len2+1];//用动态数组储存右边的数
    for (int i=0;i<len1;i++) 
	{// 把Array数组左边的数放入L数组
        L[i]=_Array[p+i];
    }
    for(int j=0;j<len2;j++) 
	{// 把Array数组右边的数放入R数组
        R[j]=_Array[q+1+j];
    }
    L[len1]=R[len2]=INT_MAX;//定义无穷大
    int i=0,j=0;
    for(int k=p;k<=r;k++) 
	{
        if(L[i]<R[j]) 
		{//小的放左边,大的放右边
            _Array[k]=L[i];
            i++;
        }
        else 
		{
            _Array[k]=R[j];
            j++;
        }
    }
}
//归并排序
void MergeSort(int _Array[],int p,int r) 
{
    if(p<r) 
	{//p:第0个;r:第n-1个数。数组至少要有两个数据
        int q;
        q=(r+p)/2;//拆分两组
        MergeSort(_Array,p,q);//拆分第0个到第 (r + p) / 2个 ,即拆分左半部分
        MergeSort(_Array,q+1,r);//拆分第(r + p) / 2个到第r个 ,即拆分右半部分
        Merge(_Array,p,q,r);//调用合并函数,从第0个到第n-1个排好
    }
}

时间复杂度分析
合并排序主要考虑两个函数的时间花销,合并函数Merge()和归并排序函数
MergeSort()。Merge ()代码中有2个长度为n的非嵌套循环,所以时间复杂度则为O(n);调用MergeSort()函数划分两部分,那每一小部分排序好所花时间则为 T[n/2],而最后把这两部分有序的数组合并成一个有序的数组Merge()函数所花的时间为 O(n),根据公式T[n] = 2T[n/2] + O(n),T[n] = O( nlogn );所以为O( nlogn )。

实验心得
通过这次实验,我学习了合并排序的分治算法,熟悉了随机数生成方法和文件读写操作。
分析实验结果发现合并排序算法消耗的时间非常短。

完整代码
分治法排序

#include<iostream>
#include<fstream>
#include<windows.h>
#include<ctime>
using namespace std;
//合并函数,q为切分点,array数组就是随机数的数组 
void Merge(int *_Array, int p, int q, int r) 
{//p:第0个;r:第n-1个数,q:第(r + p)/2个数
    int len1=q-p+1;
    int len2=r-q;
    int *L=new int[len1+1];//用动态数组储存左边的数
    int *R=new int[len2+1];//用动态数组储存右边的数
    for (int i=0;i<len1;i++) 
	{// 把Array数组左边的数放入L数组
        L[i]=_Array[p+i];
    }
    for(int j=0;j<len2;j++) 
	{// 把Array数组右边的数放入R数组
        R[j]=_Array[q+1+j];
    }
    L[len1]=R[len2]=INT_MAX;//定义无穷大
    int i=0,j=0;
    for(int k=p;k<=r;k++) 
	{
        if(L[i]<R[j]) 
		{//小的放左边,大的放右边
            _Array[k]=L[i];
            i++;
        }
        else 
		{
            _Array[k]=R[j];
            j++;
        }
    }
}
//归并排序
void MergeSort(int _Array[],int p,int r) 
{
    if(p<r) 
	{//p:第0个;r:第n-1个数。数组至少要有两个数据
        int q;
        q=(r+p)/2;//拆分两组
        MergeSort(_Array,p,q);//拆分第0个到第 (r + p) / 2个 ,即拆分左半部分
        MergeSort(_Array,q+1,r);//拆分第(r + p) / 2个到第r个 ,即拆分右半部分
        Merge(_Array,p,q,r);//调用合并函数,从第0个到第n-1个排好
    }
}
int main() 
{
	ifstream in;
	in.open("input.txt");
	ofstream out; 
    int n;
    in>>n;
    int Array[n];
    for (int i=0;i<n;i++){in>>Array[i];}
    in.close();
    clock_t start,end;
    start=clock();
    MergeSort(Array,0,n-1);
    end=clock();
    printf("时间:%fms\n",(double)(end-start)/CLK_TCK);
	out.open("output.txt");
    out<<"排序后的数组为:";
    for(int j=0;j<n;j++)
	{
        out<<Array[j]<<"  ";
    }
	out.close();
    return 0 ;
}

随机数生成

#include<stdlib.h>
#include<time.h>
#include<fstream>
#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	ofstream out("input.txt");
	out<<n<<'\n';
	srand((unsigned)time(NULL));
	for(int i=0;i<n;i++){
		out<<rand()<<' ';
		if((i+1)%10==0) out<<'\n';
	}
	out.close();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值