合并排序的递归实现
来源:互联网 发布:股票软件的数据接口 编辑:程序博客网 时间:2024/06/01 18:58
之前在博客上偶然看到一篇介绍合并排序递归实现的文章,作者给出了合并排序递归实现的代码,说用的是算法导论的思想,我看了一下代码,思路是算法导论给出的没错,但是递归条件写的有问题,作者给出的代码如下:
1 /** 2 * Merge_Sort: 归并排序的递归实现 3 * 注:算法导论上给出的合并排序算法 4 * 递归过程是将待排序集合一分为二, 5 * 直至排序集合就剩下一个元素为止,然后不断的合并两个排好序的数组 6 * T(n) = O(nlgn) 7 **/ 8 #include <stdio.h> 9 #define LEN 810 11 // 合并12 void merge(int a[], int start, int mid, int end)13 {14 int n1 = mid - start + 1;15 int n2 = end - mid;16 int left[n1], right[n2];17 int i, j, k;18 19 for (i = 0; i < n1; i++) /* left holds a[start..mid] */20 left[i] = a[start+i];21 for (j = 0; j < n2; j++) /* right holds a[mid+1..end] */22 right[j] = a[mid+1+j];23 24 i = j = 0;25 k = start;26 while (i < n1 && j < n2)27 if (left[i] < right[j])28 a[k++] = left[i++];29 else30 a[k++] = right[j++];31 32 while (i < n1) /* left[] is not exhausted */33 a[k++] = left[i++];34 while (j < n2) /* right[] is not exhausted */35 a[k++] = right[j++];36 }37 38 // merge_sort():先排序,再合并39 void merge_sort(int a[], int start, int end)40 {41 int mid;42 if (start < end)43 {44 mid = (start + end) / 2;45 printf("sort (%d-%d, %d-%d) %d %d %d %d %d %d %d %d\n",46 start, mid, mid+1, end,47 a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);48 49 // 分解 + 解决:Divide + Conquer50 merge_sort(a, start, mid); // 递归划分原数组左半边array[start...mid]51 merge_sort(a, mid+1, end); // 递归划分array[mid+1...end]52 // 合并:Combine53 merge(a, start, mid, end); // 合并54 55 printf("merge (%d-%d, %d-%d) to %d %d %d %d %d %d %d %d\n",56 start, mid, mid+1, end,57 a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);58 }59 }60 61 int main(void)62 {63 int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 };64 merge_sort(a, 0, LEN-1);65 66 return 0;67 }在merge_sort方法内并没有给出递归的出口,所以我验证了一下这段代码,结果stackoverflow了,原因很简单,递归没有出口会一直在最底层的merge那里徘徊,自己又尝试着写了java版本,代码如下:
package testfile;
public class testmerge{
public static void main(String[] args) {
int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
sort(data, left, center);
// 对右边数组进行递归
sort(data, center + 1, right);
// 合并
merge(data, left, center, right);
}
public static void merge(int [] a,int start,int mid,int end){
int n1=mid-start+1;
int n2=end-mid;
int [] left=new int[n1];
int [] right=new int[n2];
int i,j;
for(i=0;i<n1;i++){
left[i]=a[start+i];
}
for(j=0;j<n2;j++){
right[j]=a[mid+j+1];
}
i=0;j=0;
int k=start;
while(i<n1&&j<n2){
if(left[i]<right[j]){
a[k++]=left[i++];
}
else{
a[k++]=right[j++];
}
}
while(i<n1){
a[k++]=left[i++];
}
while(j<n2){
a[k++]=right[j++];
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
可以看到递归部分的return语句。经验证这个是可以跑出结果的。另外说一句自己写的时候遇到的一个小bug,在merge方法第一层while的if判断条件里,我一开始写的时间并没有用else,而是写了if(left[i]>right[j]),j结果就有了outofbounds错误,原因是在前面的if执行后i的值已经加了1,所以如果前方的if条件里left[i]是left数组的最后一个函数,那么再加1之后肯定就越界了,而用else就不会有这种问题,所以细节一定要注意。
- 合并排序的递归实现
- 递归实现合并排序
- 合并排序的非递归实现
- 合并排序的非递归实现
- 合并排序的递归实现算法
- 递归的合并排序
- 非递归实现合并排序
- 合并排序非递归实现
- 自然合并排序的java实现(合并排序的非递归实现)
- 合并两个排序的链表---递归实现
- 算法设计与分析 合并排序的递归实现算法
- 合并排序的递归算法
- 归并排序(递归实现+非递归实现+自然合并排序)
- 归并排序递归及非递归实现(自然合并排序)
- Ackerman函数的递归、全排列的递归实现、整数划分的递归、二分搜索的递归、合并排序的递归、.快速排序
- 合并排序(归并排序)的递归和非递归
- 合并排序的非递归算法
- 递归合并排序
- Java学习总结:反射机制
- 安装JBoss服务器与启动时遇到:Address already in use:bind /127.0.0.1:9990的问题的处理办法!
- 一种简单有效的个性化推荐方法
- hdu3555 Bomb
- 视频摘要与检索系统
- 合并排序的递归实现
- 再会鸟哥LINU
- Word 中添加目录的一般方法
- 关于数据库迭代更新
- hdu1863 畅通工程(判定最小生成树)
- HDU 1698 Just a Hook(线段树+lazy)
- Android 进阶
- 今天开始写博客
- linux下编译dcmtk的Android版本