1、概念
归并算法(操作、排序)是指将两个已经排序的序列合并成一个序列的操作
2、 用途
(1) 用合并算法将某个数组排序,步骤如下:
a、将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含2个元素;
b、 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含4个元素;
重复步骤2,直到所有元素排序完
(2) 用将两个有序子序合并成一个有序序列,并归操作步骤如下:
a、申请空间,大小为两个子序列之和,该空间用来存放合并后的序列;
b、设定两个指针,初始位置分别为两个已经排序序列的起始位置;
c、比较两指针所指元素,选相对小的元素放入到合并空间,并移动指针到下一个位置;
d、重复步骤3直到某一个指针达到序列尾;
e、将另一序列剩下的所有元素直接复制到合并序列尾
3、示例
(1)递归:
void mergeSort(int a,int b)// 下标,例如数组int is[5],全部排序的调用为mergeSort(0,4)
{
if(a<b)
{
int mid=(a+b)/2;
mergeSort(a,mid);
mergeSort(mid+1,b);
merge(a,mid,b);
}
}
void merge(int low,int mid,int high)
{
int i=low,j=mid+1,k=low;
while(i<=mid&&j<=high)
{
if(SrcArray[i]<=SrcArray[j])// 此处为稳定排序的关键,不能用小于
{
DstArray[k++]=SrcArray[i++];
}
else
{
DstArray[k++]=SrcArray[j++];
}
}
while(i<=mid)
{
DstArray[k++]=SrcArray[i++];
}
while(j<=high)
{
DstArray[k++]=SrcArray[j++];
}
for(i=low;i<=high;i++)// 写回原数组
{
SrcArray[i]=DstArray[i];
}
}
(2)非递归
// Merge.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <conio.h>
//函数原型
void ParallelSort(int szData[],int nLeftStartIndex,int nRightIndexStart,int nSubLen,int nTotalLen);
int main()
{
//定义变量
int a[]={1,5,3,6,7,4,2};
int nTotalElemCounts=7; // 排序元素个数
int nSubOrderLen=1; // 子序列长度初始值为
//排序
while( nSubOrderLen<nTotalElemCounts )
{
int nTmpLeftStartIndex = 0; // 左子序列起始地址,而nTmpLeftStartIndex+nLen 表示右子序列起始地址;
int nTotalSubOrderCounts = nTotalElemCounts / nSubOrderLen; // 表示子序列个数
for( int i=0;i < nTotalSubOrderCounts && nTmpLeftStartIndex < nTotalElemCounts;
nTmpLeftStartIndex = ++i*nSubOrderLen*2 )
{
ParallelSort(a, nTmpLeftStartIndex, nTmpLeftStartIndex+nSubOrderLen, nSubOrderLen, nTotalElemCounts);
}
nSubOrderLen*=2; // 子序列的长度变成原来的倍
}
//输出排序后的元素
for(int m=0;m<nTotalElemCounts;m++)
{
printf("%d\n",a[m]);
}
getch();
}
//为两个有序序列进行排序
void ParallelSort(int szData[],int nLeftStartIndex,int nRightStartIndex,int nSubLen,int nTotalLen)
{
// 用于存放临时的数据
int *szTempData = new int[nTotalLen];
memset(szTempData, 0, nTotalLen);
int flag=0;
int i=0;
int j=0;
while(i<nSubLen && j<nSubLen
&& nLeftStartIndex+i<nTotalLen
&& nRightStartIndex+j<nTotalLen ) // 每次交换的次数有两个条件:步长数和最大长度;i管start1,j管start2
{
if(szData[nLeftStartIndex+i]<szData[nRightStartIndex+j])
{
szTempData[flag++]=szData[nLeftStartIndex+i];
++i;
}
else if(szData[nLeftStartIndex+i]==szData[nRightStartIndex+j])
{
szTempData[flag++]=szData[nLeftStartIndex+i];
++i;
++j;
}
else
{
szTempData[flag++]=szData[nRightStartIndex+j];
++j;
}
}
while(i<nSubLen && nLeftStartIndex+i<nTotalLen)
{
szTempData[flag++]=szData[nLeftStartIndex+i++];
}
while(j<nSubLen && nRightStartIndex+j<nTotalLen)
{
szTempData[flag++]=szData[nRightStartIndex+j++];
}
// 将有序序列覆盖到原数组
for(i=nLeftStartIndex,j=0;i<nTotalLen && i<nLeftStartIndex+2*nSubLen;i++,j++)
{
szData[i]=szTempData[j];
}
delete [] szTempData;
}