归并排序



接下来是代码的实现:

/*
* 归并排序基本思想:
*     设数组Array[]中存放了 N个元素,初始时可以把它们看成长度为 1的N个
* 有序数组。然后,把相邻的有序字数组两两合并,得到[N/2] + 1个长度为 2 的新
* 的有序子数组。再进行两两合并,如此重复,直到得到一个长度为N的有序数组为
* 止。
* 接下来的代码中命名的解释:
*   lowerOfFirGroup   第一有序子数组的下界
*   upperOfFirGroup   第一有序子数组的上界
*   lowerOfSecGroup   第二有序子数组的下界
*   upperOfSecGroup   第二有序子数组的上界  
*   mergedLength      归并的长度
*   lengthOfArray     数组的长度  
*
*/
#include <iostream>
#include <iomanip>
using namespace std;
 
#define  Size 20
typedef int MergeredLength;
typedef int DataType;

void PaintMergedSort(DataType Array[], int lengthOfArray);
void MergeredSort(DataType Array[], int lengthOfArray);
void Merge(DataType Array[], int lengthOfArray, DataType* Swap, int mergeredLength);
int main(void)
{
	DataType Array[Size] = {
		12, 34, 45, 56, 98,
		65, 43, 32, 21, 65,
		87, 76, 76, 43, 32, 
		83, 62, 6,  89, 77};
	PaintMergedSort(Array, Size);
	MergeredSort(Array, Size);
	PaintMergedSort(Array, Size);
	return 0;
}
//输出打印
void PaintMergedSort(DataType Array[], int lengthOfArray)
{
	for(int i = 0; i < lengthOfArray; i++)
		cout<<Array[i]<<"  ";
	cout<<endl;
}
//归并排序
void MergeredSort(DataType Array[], int lengthOfArray)
{
	MergeredLength  mergeredLength = 1; //初始化归并长度为 1;
                                        //初始时可以把它们看成长度为 1 的N个字数组
	DataType*   Swap;
	Swap = new int[lengthOfArray]; //动态申请相同大小的数组空间
	while( mergeredLength < lengthOfArray)
	{
		Merge(Array, lengthOfArray, Swap, mergeredLength);
		for(int i = 0; i < lengthOfArray; i++)
			Array[i] = Swap[i];
		mergeredLength *= 2;
	}
	delete []Swap;

}
void Merge(DataType Array[], int lengthOfArray, DataType* Swap, int mergeredLength)
{
	int lowerOfFirGroup = 0;//每一次都是从第一有序子数组开始,因此第一有序子数组下界都是为 0
	int upperOfFirGroup;  // 第一有序子数组上界
	int lowerOfSecGroup;  //第二有序子数组下界
	int upperOfSecGroup; // 第二有序子数字上界
	int count = 0;//计数
/*
*    一次归并排序算法把长度为"k"的相邻有序子数组从前,后进行两两合并,得到
* 长度为"2k"的有序子数组。
* 出现两个现象:
*     (1):若数组元素的个数为"2k"的整数倍,那么两两归并正好完成n个数据元
*  素的一次归并。
*     (2):若元素的个数不是2k的整数倍,那么处理方法是:
*           A: 若剩余元素的个数 大于 k 而小于 2k, 这把前k个元素作为一个子
*         数组,把剩余的元素作为最后一个子数组。
*           B: 若剩余的元素个数小于 k, 即剩余的元素个数只够一组时,则不用再
*         进行两两归并排序。
*/
	while(lowerOfFirGroup + mergeredLength < lengthOfArray)
	{
		upperOfFirGroup = lowerOfFirGroup + mergeredLength -1;
		lowerOfSecGroup = lowerOfFirGroup + mergeredLength;
		upperOfSecGroup = (lowerOfSecGroup + mergeredLength - 1 < lengthOfArray)? //比较的三目运算法则
			                  lowerOfSecGroup + mergeredLength - 1 : lengthOfArray-1;
		int i = lowerOfFirGroup;
		int j = lowerOfSecGroup;

		for(i,j; i <= upperOfFirGroup && j <= upperOfSecGroup; count++)
		{
			if(Array[i] <= Array[j])
			{
				Swap[count] = Array[i];
				i++;
			}
			else
			{
				Swap[count] = Array[j];
				j++;
			}
		}
		while(i <= upperOfFirGroup)
		{
		   Swap[count] = Array[i];
		   count++;
		   i++;
		}
		while(j <= upperOfSecGroup)
		{
			Swap[j] = Array[j];
			count++;
			j++;
		}
    lowerOfFirGroup = upperOfSecGroup + 1;//换成下一对有序子数组的归并
	}
	//下面这步是 B(上面的)情况
	for(int i = lowerOfFirGroup; i < lengthOfArray; i++,count++)
		Swap[count] = Array[i];
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值