1035 插入与归并(25 分)算法详解与双版本代码

本题链接:https://pintia.cn/problem-sets/994805260223102976/problems/994805286714327040

分析:

本题需熟练掌握insertion sort和merge sort,其中insertion sort需在每一次排序后检查当前数组的元素是否与待比较数组的元素相等,而merge sort需要在每一次归并后检查,所以merge sort 不能是递归版本,关于merge sort的非递归版本,我在另一博客有详细解释,链接如下:

https://blog.csdn.net/qq_37729102/article/details/81908746

Insertion sort的检查次数是n,merge sort的检查次数是log2n,这样,只要掌握两个sort的算法,那么一般可以通过此题。此题也可以使用C++STL的sort函数来模拟insertion sort和merge sort,其中sort函数在n规模小时是insertion sort,故直接拿来用即可。至于insertion sort模拟merge sort,首先需要知道merge sort的二路归并原理,即对两端k个元素归并,而使用sort,则是对一段k个元素排序,再对下一段k个元素排序,执行次数是n/k。

代码: 

手写sort版:

#include<iostream>
using namespace std;
int *b=new int [100];//开头先定义临时数组,注意必须用new申请否则平台通不过 
void Merge(int *elem,int lo,int mi,int hi)
{
	//对elem数组的[lo,mi),[mi,hi)部分合并,注意右边是开区间 
	int lb=mi-lo;
	int lc=hi-mi;
	int *a=elem+lo;//a从elem的lo开始改变elem 
	int *c=elem+mi;//c从elem+mi开始到elem+hi的部分将与elem+lo到elem+mi作对比 
	for(int i=0;i<lb;b[i]=a[i++]);//b接收elem+lo到elem+mi的部分与c对比 
	for(int i=0,j=0,k=0;j<lb||k<lc;)//b与c对比完存入a 
	{
		if(j<lb&&(lc<=k||b[j]<c[k]))a[i++]=b[j++];
		if(k<lc&&(lb<=j||c[k]<=b[j]))a[i++]=c[k++];
	}
}
void MergePass(int *elem,int k,int len)
{
	int i=0;
	while(i+2*k<=len)//遍历数组 
	{
		Merge(elem,i,i+k,i+2*k);//每次对左边k个和右边k个元素归并
		i+=2*k;//合并完两个k个元素的部分后,指针位移2k个单位 
	}
	if(i+k<=len)//若有剩余数据则将剩余部分再归并一次,即左边k个右边len-i-k个 
	Merge(elem,i,i+k,len);
}
void InsertionSort(int *a,int i)
{
	int j;
	int t=a[i];
	for(j=i;j>0&&a[j-1]>t;j--)
	a[j]=a[j-1];
	a[j]=t;
}
bool Judge(int *a1,int *a2,int n)
{
	for(int i=0;i<n;i++)
	if(a1[i]!=a2[i])
	return false;
	return true;
}
void OutPut(int *a,int n)
{
	for(int i=0;i<n;i++)
	{
		cout<<a[i];
		if(i!=n-1)
		cout<<' ';
	}
}
int main()
{
	int n,a1[100],a2[100],a3[100];
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a1[i];
		a3[i]=a1[i];
	}
	for(int i=0;i<n;i++)
	cin>>a2[i];
	int k=1;//定义步长,即合并元素个数
	while(k<n)
	{
		MergePass(a3,k,n);//遍历数组并局部归并k个元素,即左边k个右边k个 
		k*=2;//两端的k个元素归并完,再对两端2k个元素归并 
		if(Judge(a3,a2,n)&&k<n)
		{
			cout<<"Merge Sort\n";
			MergePass(a3,k,n);
			OutPut(a3,n);
			return 0;
		}
	}
	delete []b;
	for(int i=1;i<n;i++)
	{
		InsertionSort(a1,i);
		if(Judge(a1,a2,n)&&i<n-1)
		{
			cout<<"Insertion Sort\n";
			InsertionSort(a1,i+1);
			OutPut(a1,n);
			return 0;
		}
	}
	return 0;
}

STL sort版:

#include<iostream>
#include<algorithm>
using namespace std;
void OutPut(int *a,int n)
{
	for(int i=0;i<n;i++)
	{
		cout<<a[i];
		if(i!=n-1)
		cout<<' ';
	}
}
int main()
{
	int n,i,k,a1[100],a2[100],a3[100];
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>a1[i];
		a2[i]=a1[i];
	}
	for(i=0;i<n;i++)
	cin>>a3[i];
	for(i=2;i<=n;i++)//sort(a,a+n)指对a的n个元素排序,故n从2开始 
	{
		sort(a1,a1+i);
		if(equal(a1,a1+n,a3)&&i+1<=n)//使用equal函数将a1与a3作对比 
		{
			cout<<"Insertion Sort\n";
			sort(a1,a1+i+1);
			OutPut(a1,n);
			return 0;
		}
	}
	for(k=2;k<=n;)
	{
		for(i=0;i<n;i+=k)//注意这里是+=k 
		sort(a2+i,a2+(i+k<=n?i+k:n));
		k*=2;//注意要乘以2 
		if(equal(a2,a2+n,a3)&&k<=n)
		{
			cout<<"Merge Sort\n";
			for(i=0;i<n;i+=k)//注意这里是+=k 
			sort(a2+i,a2+(i+k<=n?i+k:n));
			OutPut(a2,n);
			return 0;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37729102/article/details/81938961