归并排序(递归与非递归)的实现
2015-09-03 14:08
471 查看
摘要:
(1)归并排序几乎以O(NlogN)的时间界实现,是典型的分治算法;
(2)归并排序的基本思路很简单:就是将目标序列分为两个部分,将两个子序列排序好之后,再将它们合并。注意到合并两个已排序的序列只需要O(N)的时间界。
(3)对两个子序列的排序显然也是通过递归的归并排序实现的。
(4)需要注意的一个小细节是,当子序列的元素很少时,继续调用归并排序未必是一件划算的事.因此可以设置一个边界,当元素个数少于这个值时就掉用最简单的插入排序.
【1】合并的过程
合并的过程相对简单,用两个指针指向两个子序列的开始点,然后比较它们的大小.将较小的一个放入新的数组.然后将指向较小元素的指针前移一位。继续这个过程直到某一个指针达到边界.然后将另一个子序列的剩余所有元素都置入新的数组.
【2】注意的细节:如果每一次递归都创建一个新的数组那么将会占用很多的空间.因此合理的做法是在进入递归之前创建两个数组,然后用两个变量Left,Right标志子序列的边界。每一次合并的过程都是把A[Left1]到A[Right1],A[Left1+1]到A[Right2]合并到B[left1]到B[Right2];
【2】真正的排序
【3】以上的程序都是用递归的办法实现。下面用非递归的办法实现归并排序.
非递归的基本思路
(1)我们应该每次对2^i长度的子序列进行合并。例如最开始对长度为1的相邻子序列进行合并;然后对长度为2的相邻的子序列进行合并。代码如下
(1)归并排序几乎以O(NlogN)的时间界实现,是典型的分治算法;
(2)归并排序的基本思路很简单:就是将目标序列分为两个部分,将两个子序列排序好之后,再将它们合并。注意到合并两个已排序的序列只需要O(N)的时间界。
(3)对两个子序列的排序显然也是通过递归的归并排序实现的。
(4)需要注意的一个小细节是,当子序列的元素很少时,继续调用归并排序未必是一件划算的事.因此可以设置一个边界,当元素个数少于这个值时就掉用最简单的插入排序.
【1】合并的过程
合并的过程相对简单,用两个指针指向两个子序列的开始点,然后比较它们的大小.将较小的一个放入新的数组.然后将指向较小元素的指针前移一位。继续这个过程直到某一个指针达到边界.然后将另一个子序列的剩余所有元素都置入新的数组.
【2】注意的细节:如果每一次递归都创建一个新的数组那么将会占用很多的空间.因此合理的做法是在进入递归之前创建两个数组,然后用两个变量Left,Right标志子序列的边界。每一次合并的过程都是把A[Left1]到A[Right1],A[Left1+1]到A[Right2]合并到B[left1]到B[Right2];
#include "stdafx.h" #include "malloc.h" #include "stdlib.h" #include "string.h" #define Max 10000000 int Min(int a ,int b) { return a < b ? a:b; } void Merge(int *A,int *tmp,int Left1,int Right1,int Left2, int Right2) { if(Left1==Right1&&Right1==Left2&&Left2==Right2)//只有一个元素不用合并 return; int point1 = Left1,point2 = Left2,k = Left1; //int tmp[9]; while(point1 <= Right1 && point2 <= Right2) { if(A[point1] <= A[point2]) tmp[Left1++] = A[point1++]; else tmp[Left1++] = A[point2++]; } while(point1 <= Right1) tmp[Left1 ++] = A[point1++]; while(point2 <= Right2) tmp[Left1++] = A[point2++]; for (Left1 = k;Left1<= Right2;Left1++) { A[Left1] = tmp[Left1]; } }
【2】真正的排序
void Mergesort(int *A,int *tmp,int Left,int Right) { int Center; if(Left == Right)//只有一个元素 return; Center = (Left + Right)/2; Mergesort(A,tmp,Left,Center); Mergesort(A,tmp,Center + 1,Right); //下面合并 Merge(A,tmp,Left,Center,Center+1,Right); }
【3】以上的程序都是用递归的办法实现。下面用非递归的办法实现归并排序.
非递归的基本思路
(1)我们应该每次对2^i长度的子序列进行合并。例如最开始对长度为1的相邻子序列进行合并;然后对长度为2的相邻的子序列进行合并。代码如下
void Mergesort2(int *A,int *tmp,int N) { //非递归归并 int test[9]; int number = 1;//每次合并个数 int i,Center,end; while(number <= N-1) { for( i = 0; i + number<= N ; i += number) { end = i + number - 1; Center = (i + end)/2; Merge(A,tmp,i,Center,Center+1,end); } if (i <= N-1) { //合并多出的元素 Merge(A,tmp,i-number,i-1,i,N-1); } number *= 2; } } void Msort(int A[],int N) { int i = 1,cutoff,j; while(i <= N) { i *= 2; } cutoff = i - N; int *B = (int *)malloc(sizeof(int)*i); int *tmp = (int *)malloc(sizeof(A)*N); Mergesort2(A,tmp,N); free(tmp); }
相关文章推荐
- java 的堆栈 的内存分析
- 可动态扩展的分库分表策略浅谈 - 工作点滴 - 博客频道 - CSDN.NET
- NOIP2006
- bzoj2429
- this class is not key value coding-compliant for the key progressVIew
- 可以将txt快速转换成pdf的方法分享
- Regionals 2014 >> Latin America >> 6823 - Counting substhreengs
- 前端路上的各种问题-javascript—4
- socket通信之七:Overlapped I/O 完成例程模型实现的客户/服务器模型
- 又拍网架构中的分库设计
- CodeIgniter笔记-去掉index.php
- leetCode #142 Linked List Cycle II
- MySQL导入sql文件及常用命令
- Django ajax
- 【Android基础】-基于Apache HttpClient封装的网络操作工具类
- 上台阶
- haproxy反向代理
- 在纪念中国人民抗日战争暨世界反法西斯战争胜利70周年大会上的讲话
- Linux进程查看与管理
- httpd反向代理