归并排序算法(转帖)

zm0011 2008-04-17 11:05:34
合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个 N/2 个长度为2或1的有序子序列,再两两合并,如此重复,值得得到一个长度为N的有序数据序列为止,这种排序方法称为2—路合并排序。

例如数组A有7个数据,分别是: 49 38 65 97 76 13 27,那么采用归并排序算法的操作过程如图7所示:

初始值 [49] [38] [65] [97] [76] [13] [27]

看成由长度为1的7个子序列组成

第一次合并之后 [38 49] [65 97] [13 76] [27]

看成由长度为1或2的4个子序列组成

第二次合并之后 [38 49 65 97] [13 27 76]

看成由长度为4或3的2个子序列组成

第三次合并之后 [13 27 38 49 65 76 97]

合并算法的核心操作就是将一维数组中前后相邻的两个两个有序序列合并成一个有序序列。合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。合并算法的合并次数是一个非常重要的量,根据计算当数组中有3到4个元素时,合并次数是2次,当有5到8个元素时,合并次数是3次,当有9到16个元素时,合并次数是4次,按照这一规律,当有N个子序列时可以推断出合并的次数是X(2 >=N,符合此条件的最小那个X)。
...全文
294 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
zm0011 2008-04-26
  • 打赏
  • 举报
回复
同学们都不看,我自己来顶一顶
zm0011 2008-04-26
  • 打赏
  • 举报
回复
除了3楼的代码外,另外再推举两份代码:


denghui0815的

http://download.csdn.net/user/huanyun/


haojn的

http://download.csdn.net/user/haojn


这两份程序中,极有可能会选出4月线程赛的最佳方案。
yangyun10 2008-04-26
  • 打赏
  • 举报
回复
非递归的归并排序,g_InputData,m_TargetBuff是外部分配的缓冲
//direction排序的方向
void WORK(int LocalPos,int ThreadId,int ThreadStep,int ThreadMaxLimit,bool ThreadDirection,int StartPos){
//注意不要越界
int *TaskTarget;
int *TaskSource;
if(LocalPos&1){
TaskTarget=m_TargetBuff+StartPos;
TaskSource=g_InputData+StartPos;
}
else{
TaskSource=m_TargetBuff+StartPos;
TaskTarget=g_InputData+StartPos;
}
//ThreadId说明我存储的数据位置范围
int Seg1Ptr,Seg2Ptr,NewSegPtr;
int Seg1Min=ThreadId*ThreadStep;
int Seg2Max=(ThreadId+1)*ThreadStep-1>ThreadMaxLimit-1?ThreadMaxLimit-1:(ThreadId+1)*ThreadStep-1;

int Seg2Min=ThreadId*ThreadStep+ThreadStep/2;
int Seg1Max=ThreadId*ThreadStep+ThreadStep/2-1;
//检查上层排序是否完成
if(Seg2Max-Seg1Min<ThreadStep/2)
{//不用归并排序了,此段已排好
for(NewSegPtr=Seg1Min;NewSegPtr<=Seg2Max;NewSegPtr++){
TaskTarget[NewSegPtr] = TaskSource[NewSegPtr];
}
return;
}
//归并排序,从Source,存储到TargetBuff里
//ThreadDirection :true由小往大排;false ;由大往小排
Seg1Ptr=NewSegPtr=Seg1Min;
Seg2Ptr=Seg2Min;
do{
if (ThreadDirection?(TaskSource[Seg1Ptr] <= TaskSource[Seg2Ptr]):(TaskSource[Seg1Ptr] >= TaskSource[Seg2Ptr])){
TaskTarget[NewSegPtr++] = TaskSource[Seg1Ptr++];
}
else{
TaskTarget[NewSegPtr++] = TaskSource[Seg2Ptr++];
}
}while(Seg1Ptr<=Seg1Max&&Seg2Ptr<=Seg2Max);
if(Seg1Ptr<=Seg1Max){
for(;Seg1Ptr<=Seg1Max;Seg1Ptr++){
TaskTarget[NewSegPtr++] = TaskSource[Seg1Ptr];
}
return;
}
if(Seg2Ptr<=Seg2Max){
for(;Seg2Ptr<=Seg2Max;Seg2Ptr++){
TaskTarget[NewSegPtr++] = TaskSource[Seg2Ptr];
}
}
}
void MergSortSub(int StartPos,int EndPos,bool direction){
int Step=1;
int Id=0;
int SegLen=0;
int TaskMaxNum=EndPos-StartPos;
int TaskPos=0;
if(TaskMaxNum==1)
{
TaskPos=1;
WORK (TaskPos,Id,Step*2,TaskMaxNum,direction,StartPos);
}
else{
while(Step<TaskMaxNum){
TaskPos++;
SegLen=0;
Id=0;
while(SegLen<TaskMaxNum){
WORK (TaskPos,Id,Step*2,TaskMaxNum,direction,StartPos);
Id++;
SegLen+=Step*2;
}
Step+=Step;
}
}
}
HellMoxi 2008-04-26
  • 打赏
  • 举报
回复
我在看呐,有代码演示么???我知道这个算法的过程,但是居体代码还是不清楚啊!

566

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧