关于归并排序的问题

课程设计用归并排序出现了一些有趣的问题, 首先是B题, 配套的代码第41行S相当于临时空间,

 1 #include <iostream>
 2 using namespace std;
 3 #define  MAXSIZE  1000001
 4 typedef struct
 5 {
 6     int key;
 7 }RedType;
 8
 9 typedef struct
10 {
11     RedType *r;
12     int length;
13 }SqList;
14
15 void Create_Sq(SqList &L,int n)
16 {
17     int i;
18     for(i=1;i<=n;i++)
19     {
20         scanf("%d",&L.r[i].key);
21         L.length++;
22     }
23 }
24 void Merge(RedType R[],RedType T[],int low,int mid,int high)
25 {
26     int i,j,k;
27     i=low; j=mid+1;k=low;
28     while(i<=mid&&j<=high)
29     {
30         if(R[i].key<=R[j].key) T[k++]=R[i++];
31         else T[k++]=R[j++];
32     }
33     while(i<=mid)
34         T[k++]=R[i++];
35     while(j<=high)
36         T[k++]=R[j++];
37 }
38 void MSort(RedType R[],RedType T[],int low,int high)
39 {
40     int mid;
41     RedType *S=new RedType[MAXSIZE];
42     if(low==high) T[low]=R[low];
43     else
44     {
45         mid=(low+high)/2;
46         MSort(R,S,low,mid);
47         MSort(R,S,mid+1,high);
48         Merge(S,T,low,mid,high);
49     }
50     delete []S;
51 }
52 void MergeSort(SqList &L)
53 {
54     MSort(L.r,L.r,1,L.length);
55 }
56 void show(SqList L)
57 {
58     int i;
59     printf("%d",L.r[1].key);
60     for(i=2;i<=L.length;i++)
61         printf(" %d",L.r[i].key);
62     printf("\n");
63 }
64 int main()
65 {
66     int n;
67     while(scanf("%d",&n)&&n!=0)
68     {
69         SqList R;
70         R.r=new RedType[MAXSIZE+1];
71         R.length=0;
72         Create_Sq(R,n);
73         MergeSort(R);
74         show(R);
75     }
76         return 0;
77 }
没有第50行 delete []S;这一行时内存超限.加上后提交结果如下.
运行编号 用户 问题 结果 内存 耗时 语言 代码长度 提交时间
23305 tuhao
B
正确
75732

15120
C++/Edit 1669 B 2014-06-16 11:45:19
但是在数据加强的C题依然是内存超限, 注意到第41行的new反复调用导致MLE,能不能减少这方面的使用呢?首先直接的方式把S改成外部(全局)数组, 但是这样是不行的, 这里指出一下原因,因为S为全局数组,递归调用下去将出现merge(S, S)的情况.下面给出我的一个方法
 1 //算法8.11 归并排序
 2 #include <iostream>
 3 using namespace std;
 4 #define  MAXSIZE  1000000                                 //顺序表的最大长度
 5 typedef struct
 6 {
 7     int key;
 8     char *otherinfo;
 9 }RedType;
10
11 typedef struct
12 {
13     RedType *r;
14     int length;
15 }SqList;
16
17 RedType S[MAXSIZE];
18 void Create_Sq(SqList &L,int n)
19 {
20     int i;                            //输入个数
21     for(i=1;i<=n;i++)
22     {
23         scanf("%d",&L.r[i].key);
24         L.length++;
25     }
26 }
27
28 //用算法8.10 相邻两个有序子序列的归并
29 void Merge(RedType R[],RedType T[],int low,int mid,int high)
30 {
31    //将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]
32     int i,j,k;
33     i=low; j=mid+1;k=low;
34     while(i<=mid&&j<=high)
35     {
36         //将R中记录由小到大地并入T中
37         if(R[i].key<=R[j].key) T[k++]=R[i++];
38         else T[k++]=R[j++];
39     }
40     while(i<=mid)                                    //将剩余的R[low..mid]复制到T中
41         T[k++]=R[i++];
42     while(j<=high)                                   //将剩余的R[j.high]复制到T中
43         T[k++]=R[j++];
44     for(i = low; i <= high; i++)
45         R[i] = T[i];
46 }//Merge
47
48 void MSort(RedType R[],int low,int high)
49 {
50     //R[low..high]归并排序后放入T[low..high]中
51     int mid;
52
53     if(low < high) {
54         mid=(low+high)/2;                           //将当前序列一分为二,求出分裂点mid
55         MSort(R,low,mid);                            //对子序列R[low..mid] 递归归并排序,结果放入S[low..mid]
56         MSort(R,mid+1,high);
57         //对子序列R[mid+1..high] 递归归并排序,结果放入S[mid+1..high]
58         Merge(R, S, low,mid,high);
59
60     }//else
61 }// MSort
62
63 void MergeSort(SqList L)
64 {
65     //对顺序表L做归并排序
66     MSort(L.r,1,L.length);
67 }//MergeSort
68 void show(SqList &L)
69 {
70     int i;
71     printf("%d",L.r[1].key);
72     for(i=2;i<=L.length;i++)
73         printf(" %d",L.r[i].key);
74     printf("\n");
75 }
76
77 int main()
78 {
79     SqList R;
80     R.r=new RedType[MAXSIZE+1];
81     int n;
82     while(scanf("%d",&n)&&n!=0){
83         R.length=0;
84         Create_Sq(R,n);
85         MergeSort(R);
86         show(R); }
87         return 0;
88 }

做的改动很小

(1) 第17行, S为全局数组, 只有一个,无须递归分配

(2)修改MSort(RedType R[],int low,int high), 原来是四个参数,现在是三个, 即将R的low 至high区间元素归并到R中

(3)修改Merge,多了44,45行, 先将两部分R的内容归并到S,然后拷贝回R, 当然这个拷贝的开销是我们不期望的.

进一步的话题:

我们还可以取消拷贝的开销, 怎么做?可以考虑两个数组R,S,  R->S->R->S->..., R归并到S,S归并到R, 滚动进行,实现起来按自底向上容易一些, 但是自顶向下的递归实现不是很直观,建议同学们尝试一下.

关于归并排序的问题

时间: 2025-01-02 09:07:07

关于归并排序的问题的相关文章

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

codeforces 414C C. Mashmokh and Reverse Operation(归并排序求逆序对)

题目链接: C. Mashmokh and Reverse Operation time limit per test 4 seconds memory limit per test 512 megabytes input standard input output standard output Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university

归并排序(Merge Sort)

更详细的请看这篇博文:http://www.cnblogs.com/jingmoxukong/p/4308823.html 我只做个人学习和补充 基于分治法的排序,比较简单.个人感觉其核心是数组左右拆分之后类似队列的比较.类似两两合并之类的算法都可以参考 分为3个步骤,拆开为树结构遍历->向上合并 特别做了一张gif来更好的理解归并排序 左边集合比较通过就左边索引前进,右边集合比较通过则右边索引前进 比较结果放入结果数组中 最后如果多出一个就把这一个直接加入结果数组 为了易于学习,代码直接使用了

两路归并排序

链表两路归并 #include<iostream> #include<assert.h> using namespace std; struct node { int val; node * next; node(int v) { val=v; next=NULL; } }; node * merge(node* list1 , node * list2) { assert(list1!=NULL&&list2!=NULL);//括号中是希望出现的正确的情况  no

算法基础:分治模式,归并排序ΘΘΘΘΘΘ知识小结

1.分治模式在每层递归时都有三个步骤:分解,解决,合并 2.归并排序算法完全遵循分治模式: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列 解决:使用归并排序递归的排序两个子序列 合并:合并两个已排序的子序列以产生已排序的答案 3.分析分治算法所需要的时间计算: 假设T(n)是规模为n的一个问题的运行时间,若问题足够小,如对某个常量c,n≦c,则直接求解需要常量时将,我们将其写作Θ(1).假设吧原问题分解成a个子问题,每个子问题的规模是原问题的1/b(对归并排序,a和b都为2,然

归并排序

基本思想: 1)首先需要一个临时空间temp用来存放合并后的元素,长度为排列好的元素总个数. 2)取两个指针,分别为左右部分数组的头元素. 3)比较指针指向元素,将较小(较大)的那个放入temp(注意相等时不做元素位置交换),并将两指针向后移动一个step. 4)循环步骤3直到其中一段数组没有剩余元素(其中一段被遍历完). 5)将还有元素剩余的另外一半数组元素直接放入temp尾部 代码实现: public static void merge(int[] list, int left, int m

基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

冒泡排序 public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } } 选择排序 publ

利用Python实现归并排序

利用python进行归并排序,摘抄自http://blog.csdn.net/minxihou/article/details/51821052 "代码真的不是一气呵成的,而且也不是想当然写出来的.可能需要反复断点中断来查看是否有逻辑错误.在理解了问题的基础下我们需要先把大体的代码框架最好先写出来,特别是主要的逻辑判断语句.但是不需要太care我循环体或者判断里面语句怎么实现,当你把这一步做到的时候能避免很多不必要的错误发生." 1 import random 2 3 def Conf

面试必考三大排序算法C++代码(快速排序、归并排序、堆排序)

前两个为C++风格代码,后一个为C风格代码,除了输入输出,其它无差别,但C输入输出要比C++更快. 快速排序 1 #include <iostream> 2 using namespace std; 3 4 void swap(int num[], int i, int j) 5 { 6 int temp = num[i]; 7 num[i] = num[j]; 8 num[j] = temp; 9 } 10 11 int partition(int num[], int left, int

python实现归并排序,归并排序的详细分析。

学习归并排序的过程是十分痛苦的.它并不常用,看起来时间复杂度好像是几种排序中最低的,比快排的时间复杂度还要低,但是它的执行速度不是最快的.很多朋友不理解时间复杂度低为什么运行速度不一定快,这个不清楚的伙伴可以看下我之前发表的文章http://www.cnblogs.com/Lin-Yi/p/7301535.html看完之后也许你会对时间复杂度有一个新的认识. 我谈的观点往往不是官方的定义,我希望能帮助更多基础薄弱的同学读懂思想~ 归并排序: 先分开再合并,分开成单个元素,合并的时候按照正确顺序合