求助:如何实现非递归的2路归并排序?

ReverseEngineering 2009-07-05 11:55:36
严蔚敏,吴伟民的数据结构的p284页,说递归形式的2路归并排序形式简洁,但实用性很差!

为什么这么说?为什么实用性差?

然后介绍其非递归的算法在 horowitz 和 sahni 的 Fundamentals of computer algoritm 。

这本书有没电子版的,搜了一下,貌似有同名的,但我没有所谓的积分,无法下载验证!真是悲哀!!!!

那位老大能给我这本书的电子版,或者给出书中的非递归形式算法。

求书,也求算法!

其他经典算法书除了mit的那本我下载过了,其他的我也想要!

电邮:384372004@qq.com

万分感激!
...全文
681 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rachel 2009-07-10
  • 打赏
  • 举报
回复
学习!
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ReverseEngineering 的回复:]
hairetz

您是高手,不过我对比您的代码和您指出的博客的代码发现一个问题:

if(mid>=num) //下标不能溢出
mid=num-1;
if(right>=num)
right=num-1;
merge(v,j,mid,right);

博客指出:“若i≤n且i+length-1≥n时,则剩余一个子文件轮空,无须归并”
对应到您的代码:就是当 j 小于 num ,mid >= num 时,您的代…
[/Quote]

呵呵,确实,楼主真是细心啊。
虽然这些merge调用本身不影响效率,不过确实不需要调用。

ps:3楼代码为何跟我一样呢?
ReverseEngineering 2009-07-09
  • 打赏
  • 举报
回复
hairetz

您是高手,不过我对比您的代码和您指出的博客的代码发现一个问题:

if(mid>=num) //下标不能溢出
mid=num-1;
if(right>=num)
right=num-1;
merge(v,j,mid,right);

博客指出:“若i≤n且i+length-1≥n时,则剩余一个子文件轮空,无须归并”
对应到您的代码:就是当 j 小于 num ,mid >= num 时,您的代码多做了一次归并。

不知道,我判断的多做了一次归并的结论是否正确,讨教!
sunzerui 2009-07-08
  • 打赏
  • 举报
回复
顶一楼!
ReverseEngineering 2009-07-07
  • 打赏
  • 举报
回复
承蒙二位帮助 ,不胜感动 !

一时还不能理解其中细节。

等看懂后,立刻结贴!
  • 打赏
  • 举报
回复
void merge(int v[],int left,int mid,int right)
{
int i,j,k=0;
i=left;
j=mid+1;
int *temp=new int[right-left+1];
while(i<=mid&&j<=right)
temp[k++]=(v[i]<=v[j])?v[i++]:v[j++];
while(i<=mid)
temp[k++]=v[i++];
while(j<=right)
temp[k++]=v[j++];
for(i=left,j=0;i<=right;++i,++j)
v[i]=temp[j];
delete []temp;
}



书的话去IT168找找
祝福
  • 打赏
  • 举报
回复
http://hi.baidu.com/yeetoo/blog/item/25c160eca8ece0d32f2e21ba.html

具体的分析可以参考这里。
上面的代码是自底向上的写法
  • 打赏
  • 举报
回复
非递归的2路归并很正常啊。

以前写过一个,用循环实现即可


#pragma warning(disable:4786)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <math.h>

using namespace std;

const int NUM=20;



int arr[] = {1,10,11,5,6,15,0,15,16,14,0,8,17,15,7,19,17,1,18,7};

void merge(int v[],int left,int mid,int right) //合并[left,mid]和[mid+1,right]
{
int i,j,k=0;
i=left; //i为第一路的下标
j=mid+1; //j为第二路的下标
int *temp=new int[right-left+1];
while(i<=mid&&j<=right)
temp[k++]=(v[i]<=v[j])?v[i++]:v[j++]; //依次合并2路到temp数组
while(i<=mid)
temp[k++]=v[i++];
while(j<=right)
temp[k++]=v[j++];
for(i=left,j=0;i<=right;++i,++j) //合并完数据写回v数组
v[i]=temp[j];
delete []temp;
}

void merge_sort(int v[],int num)
{
int i,size,j,mid,right;
for(i=1;i<num;i*=2) //log(n)趟归并
{
size=i-1;
j=0;
while(j<num)
{
mid=j+size;
right=j+2*size+1;
if(mid>=num) //下标不能溢出
mid=num-1;
if(right>=num)
right=num-1;
merge(v,j,mid,right);
j=right+1;
}
}
}

void main()
{
int j;
merge_sort(arr, NUM);
for(j=0; j<NUM; j++)
printf("%d ", arr[j]);
printf("\n");
}

33,006

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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