归并排序

分治法思路:

1.分解:把大问题分解为若干个小问题

2.解决:递归地解决各个小问题,当子问题的规模足够小,则直接求解

3.合并:合并各个小问题的解,从而得到大问题的解


归并排序排序:

1.分解:分解带排序的n个元素的序列,使其分成各具有n/2个元素的两个子序列

2.解决:使用归并排序递归地排序两个子序列

3.合并:合并两个已排好序的子序列

//归并排序(小到大,有哨兵)

#include <iostream>
using namespace std;
void merge_sort(int a[],int top,int bott);
void merge(int a[],int top,int mid,int bott);
const int maxn=10000;
int main()
{
	int a[maxn];
	int n,i;
	cin>>n;
	for (i=0;i<n;i++)
		cin>>a[i];
	merge_sort(a,0,n-1);//进入归并排序
	for (i=0;i<n;i++)
		cout<<a[i]<<' ';
	cout<<endl;
	return 0;
}
//merge_sort
void merge_sort(int a[],int p,int r)
{
	int q;
	if (p<r)
	{
		q=(p+r)/2;
		merge_sort(a,p,q);//左边排序
		merge_sort(a,q+1,r);//右边排序
		merge(a,p,q,r);//合并
	}
}
//merge
void merge(int a[],int p,int q,int r)
{
	int left[maxn],right[maxn];
	int n1,n2,i,j,k;
	n1=q-p+1;//左边的元素个数
	n2=r-q;//右边的元素个数
	for (i=0;i<n1;i++)
		left[i]=a[p+i];//把a中的前半元素复制到left
	for (j=0;j<n2;j++)
		right[j]=a[q+1+j];//把a中的后半元素复制到right
	left[n1]=99999;//左边的哨兵
	right[n2]=99999;//右边的哨兵
	i=0;//左边的下标
	j=0;//右边的下标
	//把left和right重新复制回a,使a成为排好序的序列
	for (k=p;k<=r;k++)
	{
		if (left[i]<=right[j])
		{
			a[k]=left[i];
			i++;
		}
		else 
		{
			a[k]=right[j];
			j++;
		}
	}
}


//归并排序(小到大,无哨兵)

#include <iostream>
using namespace std;
void merge_sort(int a[],int top,int bott);
void merge(int a[],int top,int mid,int bott);
const int maxn=10000;
int main()
{
	int a[maxn];
	int n,i;
	cin>>n;
	for (i=0;i<n;i++)
		cin>>a[i];
	merge_sort(a,0,n-1);//进入归并排序
	for (i=0;i<n;i++)
		cout<<a[i]<<' ';
	cout<<endl;
	return 0;
}
//merge_sort
void merge_sort(int a[],int p,int r)
{
	int q;
	if (p<r)
	{
		q=(p+r)/2;
		merge_sort(a,p,q);//左边排序
		merge_sort(a,q+1,r);//右边排序
		merge(a,p,q,r);//合并
	}
}
//merge
void merge(int a[],int p,int q,int r)
{
	int left[maxn],right[maxn];
	int n1,n2,i,j,k;
	n1=q-p+1;//左边的元素个数
	n2=r-q;//右边的元素个数
	for (i=0;i<n1;i++)
		left[i]=a[p+i];//把a中的前半元素复制到left
	for (j=0;j<n2;j++)
		right[j]=a[q+1+j];//把a中的后半元素复制到right
	i=0;//左边的下标
	j=0;//右边的下标
	//把left和right重新复制回a,使a成为排好序的序列
	for (k=p;k<=r;k++)
	{
		if (i==n1)	//当left已没有元素,将right剩余的元素复制到a中
		{
			a[k]=right[j];
			j++;
		}
		else if(j==n2) //当right已没有元素,将left剩余的元素复制到a中
		{
			a[k]=left[i];
			i++;
		}
		else //当left和right均还有元素时,比较当前left[i]和right[i]的大小,将小的复制回a中
		{
			if (left[i]<=right[j])
			{
				a[k]=left[i];
				i++;
			}
			else 
			{
				a[k]=right[j];
				j++;
			}
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值