分享,合并(分治法)排序,mergeSort

xladykiller 2010-10-10 06:19:51
合并排序的关键步骤在于合并步骤中的合并两个已排序子序列。为做排序,引入一个辅助过程merger(A,p,q,r),其中A是个数组,pqr是下标,满足p<= q < r。该过程假设A[p..q]和A[q+1..r]都已排序,并将它们合并成一个已经排好序的子数组代替当前子数组A[p..r]
#include<stdio.h>
#include<stdlib.h>
void merger(int * A,int p,int q,int r);
void mergerSort(int * A,int p,int r);
int main()
{
int A[10] = {0};
int i = 0;

for(i = 0;i < 10;i++)
{
scanf("%d",A + i);
}

printf("输入为:\n");
for(i = 0;i < 10;i++)
{

printf("%d",A[i]);
}
mergerSort(A,0,9);
printf("\n排序后:\n");
for(i = 0;i < 10;i++)
{
printf("%d",A[i]);
}
printf("\n");
return 0;
}
void merger(int * A,int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q ;
int i = 0,k = 0,j = 0;
int * L = (int*)malloc(sizeof(int) * n1 + 1);
int * R = (int *)malloc(sizeof(int) * n2 + 1);
for(i = 0;i < n1;i++)
{
L[i] = A[p + i];
}
L[i] = 99999;
for(i = 0;i < n2;i++)
{
R[i] = A[q + i + 1];
}
R[i] = 99999;
i = j = 0;

for(k = p;k <= r;k++)
{
if(L[i] < R[j])
{
A[k] = L[i];
i++;
}
else
{
A[k] = R[j];
j++;
}
}
free(R);
free(L);
}
void mergerSort(int * A,int p,int r)
{
int mid = 0;
if(p < r)
{
mid = (r + p) / 2;
mergerSort(A,p,mid);
mergerSort(A,mid + 1,r);
merger(A,p,mid,r);
}
}

运行结果:
chu@szcdebian:~/code/merge-sort$ gcc -o merge merge-sort.c
chu@szcdebian:~/code/merge-sort$ ./merge
9 0 6 8 7 3 4 2 5 1
输入为:
9068734251
排序后:
0123456789
chu@szcdebian:~/code/merge-sort$
...全文
1133 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
x5624181 2011-11-02
  • 打赏
  • 举报
回复
hao~~~
passball 2011-01-03
  • 打赏
  • 举报
回复
不错,可以执行。。。
滴水梵音 2010-12-23
  • 打赏
  • 举报
回复
这是把《算法导论》中关于归并排序算法的伪代码实现了一下,值得注意的是申请内存空间未必都成功,需要添加排错机制,才能让算法具有高效性的同时,还具有可测试性、可维护性等。
xladykiller 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 ethan_hu 的回复:]

纯 merge_sort 很慢,特别是在大规模输入时,配合插入排序可以提高一倍性能。看这个帖子:
http://topic.csdn.net/u/20100807/17/9b5bfcd0-8a87-4d36-89fd-db8c4ee1bfa8.html
[/Quote]
呵呵,你理解错了,合并排序不慢的。你指的那个贴子是说在问题规模相当小的时候,用插入排序会比合并快,(尽管合并排序最坏情况运行时间为O(nlgn),插入排序的最坏运行时间为O(n^2),但是插入排序的常数因子使得它在n较小时,运行要更快一些。)所以他把插入跟合并两个排序合起来用,在问题分解到足够 小的时候用插入。
xladykiller 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 shi3590 的回复:]

进行了一些改进。
C/C++ code

void merger(int * A,int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q ;
int i = 0,k = 0,j = 0;
int * L = (int*)malloc(sizeof(int) * n1 + 1);
int * R =……
[/Quote]


R[i] = 99999;
L[i] = 99999;
这两行其实是要表示正无穷。只是我随手写了个大一点的数而已。

shi3590 2010-10-11
  • 打赏
  • 举报
回复
进行了一些改进。

void merger(int * A,int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q ;
int i = 0,k = 0,j = 0;
int * L = (int*)malloc(sizeof(int) * n1 + 1);
int * R = (int *)malloc(sizeof(int) * n2 + 1);
for(i = 0;i < n1;i++)
{
L[i] = A[p + i];
}
//L[i] = 99999;
for(i = 0;i < n2;i++)
{
R[i] = A[q + i + 1];
}
//R[i] = 99999;
i = j = 0;

for(k = p;k <= r;k++)
{
if ((i<n1&&j==n2)||(i<n1&&j<n2&&L[i] < R[j]))
A[k] = L[i++];
else if ((i==n1&&j<n2)||(i<n1&&j<n2&&L[i] >= R[j]))
A[k] = R[j++];
}
free(L);
free(R);
}
Ethan_Hu 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 hslinux 的回复:]
弱弱的问句:跟快速排序相比较,两者都有什么优缺点?

越看越像快速排序。。。。。。
[/Quote]

快排的平均性能很好,很紧凑,若随机化的哨兵选择实现的好,几乎很难出现最糟的O(n^2)的情形,它是原地排序。
正统的归并实现时间界是O(nlgn),空间界是O(n),非原地,通常比快排慢一倍。
Ethan_Hu 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 xladykiller 的回复:]

引用 10 楼 ethan_hu 的回复:

纯 merge_sort 很慢,特别是在大规模输入时,配合插入排序可以提高一倍性能。看这个帖子:
http://topic.csdn.net/u/20100807/17/9b5bfcd0-8a87-4d36-89fd-db8c4ee1bfa8.html

呵呵,你理解错了,合并排序不慢的。你指的那个贴子是说在问题规模相当小的时候,用插入排序……
[/Quote]

我说 pure merge sort 很慢是因为它比标准库的排序慢上一倍,若标准库需要1分钟,那么你的实现就要2分钟,这难道不算慢?你有过在屏幕前长时间等待计算结果的经历吗,这种感觉非常糟糕!
hslinux 2010-10-11
  • 打赏
  • 举报
回复

弱弱的问句:跟快速排序相比较,两者都有什么优缺点?

越看越像快速排序。。。。。。
de_seven 2010-10-11
  • 打赏
  • 举报
回复
昨天刚上完算法课 就讲了合并...
下午上了课回来自己也写写看看
liutengfeigo 2010-10-11
  • 打赏
  • 举报
回复
一直想写,自己写不出,收下了
Ethan_Hu 2010-10-10
  • 打赏
  • 举报
回复
纯 merge_sort 很慢,特别是在大规模输入时,配合插入排序可以提高一倍性能。看这个帖子:
http://topic.csdn.net/u/20100807/17/9b5bfcd0-8a87-4d36-89fd-db8c4ee1bfa8.html
lly212 2010-10-10
  • 打赏
  • 举报
回复
ls 很强大 我第一次见到啊 真是捡到牛人了
harderman 2010-10-10
  • 打赏
  • 举报
回复
楼主强大.
S_zxing 2010-10-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xladykiller 的回复:]

引用 4 楼 s_zxing 的回复:

写得很好
楼主,能不能解释下什么叫分治
不懂…… 指教下

有很多算法在结构上是递归的,为了解决一个问题,算法要一次或多次地递归调用其自身来解决相关的子问题。这此算法通常用的就是分治法:将原问题分成N个规模小而结构与原问题相似的子问题,递 归解决之,然后再合并结果。就得到原问题的解了。
一般来讲就是
1。分解。
2。解决。
3。合并。……
[/Quote]
谢谢了……
xladykiller 2010-10-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 s_zxing 的回复:]

写得很好
楼主,能不能解释下什么叫分治
不懂…… 指教下
[/Quote]
有很多算法在结构上是递归的,为了解决一个问题,算法要一次或多次地递归调用其自身来解决相关的子问题。这此算法通常用的就是分治法:将原问题分成N个规模小而结构与原问题相似的子问题,递 归解决之,然后再合并结果。就得到原问题的解了。
一般来讲就是
1。分解。
2。解决。
3。合并。
wing_0706 2010-10-10
  • 打赏
  • 举报
回复
强大了。。能详细说说吗。。谢谢了。。
S_zxing 2010-10-10
  • 打赏
  • 举报
回复
写得很好
楼主,能不能解释下什么叫分治
不懂…… 指教下
dreamhunter_lan 2010-10-10
  • 打赏
  • 举报
回复
不错,也准备写一个看看。
yyg990441 2010-10-10
  • 打赏
  • 举报
回复
好强大的算法啊~~~
加载更多回复(1)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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