归并排序问题集

归并排序问题集
归并排序问题集

归并排序

问题描述:假设某一数组的项目未排序,这些项目将被拆分为相同大小的两半,并对每一半进行排序,然后将这两半合并成一个有序数组。通过调用归并排序(Mergesort) 例程,对每一半进行递归排序(该例程会将数组拆分为两半,对每一半执行排序,然后将这两半合并成一个有序数组)。可以通过使用某些数据结构(通常为堆栈)模拟递归调用来编写任何递归算法的迭代版。

目标:本次挑战的目标是编写一个归并排序算法的并行(线程化)版。应用程序将会读取一个在运行时选定的输入文本文件, 该文件包含的是将要排序的一组整数。文件的第一行将是将要排序的整数的总数 (N),后面跟有 N 个整数,每行一个。文件内的整数数量将小于2^28 – 1。排序后的结果必须输出到另一个文本文件 (sorted.out),每行一个整数。

限制:不可使用英特尔? 线程构建块并行排序算法和其他任何外部排序库函数。也不可使用其他任何排序算法在归并排序算法的递归过程中制造“短路”。因为应用程序会在执行过程中的某些时候合并相同大小的列表。

有关归并排序问题集的问题

摘自 Clay 于 2008 年 4 月的博客,如果想要参与讨论,请点击这里。

问答一:

问题:

我有一个问题,是关于“不可使用其他任何排序算法在归并排序算法的递归过程中制造‘短路’。因为应用程序会在执行过程中的某些时候合并相同大小的列表。”这一限制的。是否可以将归并排序算法(例如,四个元素组成的数组)展开成为线性顺序排列的比较交换运算,并对这些运算进行硬编码?

回答:

不可以,按该问题的描述,禁止这样做。

问答二:

问题:

我有一个关于问题描述的问题。可以对算法做一些改进吗?例如,二分归并排序或多路归并排序。还有,N 的个数为多少?

回答:

嗯,我们还没有考虑到这一点。但只要是归并排序算法,尤其是自身趋于并行时,就可以对它做一些改进。一定要将您选择的算法以及在源文件中编码的方法记录下来。

N 的最大值为 (2^28)-1。但您可以放心的是,这个数据一定适合该测试机的内存。

问答三:

问题:

由于传统的归并排序会占用数据设定的两倍空间,内存可以存得下所有的数据吗?

回答:

可以,内存会为复制的数据备有足够的空间。

问答四:

问题:

Knuth 在 TAOCP 中描述了许多不同的通过合并来排序的方法。例如,在 5.2.4 部分中的算法 S,该算法并没有使用问题描述中提到的堆栈。还有 Batcher 的通过合并交换排序(5.2.2 部分的算法 M)。这些合并排序的算法可用吗?如果可用,可以对它们进行合并吗?

回答:

我有 TAOCP 第三册的初版(翻箱倒柜才找到),我们认为算法 S (5.2.4) 是传统的归并排序算法,是可用的。

算法 M (5.2.2) 也是可用的。考虑到已知例子的数据的比较和运转,我们可以

看到正在合并的排序列表(尽管它们并非在同一物理位置上)。

房间分配问题集的评判准则

摘自 Clay 于 2007 年 12 月 5 日的博客,如果想要参与讨论,请点这里。

让我先来解释一下这个问题集中执行分数与时间分数的计算方法吧。

对于运行的每个数据集,每位参赛选手都将获得一个执行时间排名和一个最终TD 排名。时间越短,排名越高;TD分数越低,排名也越高。数字越小表示排名越“高”。TD分数的排名将先乘以三(3),然后再加到执行时间的排名上。所有数据集的排名总合将加在一起,最终生成一个净分数(Net Score)。净分数最低的参赛者将获得 100 分,净分数第二低的参赛者将获得 99 分,以此类推。(举例如下)

我们使用乘数的目的是为了更好地进行分组。此举试图避免程序只是简单地读取数据、在同组作品的基础上稍做改动,便输出自己的结果。这种程序可能会实现最低的执行时间,但是也将有可能得到最差的 TD 最终分数。另一方面,虽然用完 120 秒的程序可获得最佳的最终 TD 分数,但他将在执行时间中排名最低。如果第三位参赛选手使用了 50 秒,并获得了一个TD 分数,接近最佳得分(由另一位用满 2 分钟的选手获得),那么我们认为他更应该获得一个很好的最终总分。

我们采用这种计分方法,是为了让所有参赛选手都能思考一下:花费更多时间以求提高最终 TD 分数,以及花费较短时间来获得相近得分(通过线程)之间的利弊权衡。

举例:

目标平台– Windows

摘自 Clay 于 2007 年 11 月 15 日的博客,如果想要参与讨论,请点这里。

为了尽可能多地为那些希望深入了解评价平台的人们提供更多信息,我们在此提供了一些关于目标处理器及编译器软件的系统和软件信息。遗憾地是,由于恰巧赶上系统(这些系统在我开始撰写本消息前,刚刚断电)迁移前的周末,因此目前我们无法为您提供所有的较小版本号。下面是我们记录的有关系统信息的一个列表。一旦机器恢复运行,我们将获得更多详情,并在这里发布。

(请注意:这些规范会随着硬件或软件的升级而有所更改,届时不会发出警告。)?操作系统(OS)版本:Microsoft Windows Server 2003 64 位企业版Service Pack 2

?Visual Studio 2005 (8.0.x) and .NET Framework 2.0.x

?英特尔? 编译器 10.0.x (包括 64 位和 32 位两种版本)

?英特尔? 线程构建模块(2.0 版)

?Sun Java version 6.0

?处理器应与 Linux 系统上所用系统相同(2.667 GHz、4GB 内存)。

如果您对提交信息所用的编译器有任何特殊要求,请务必明确标注在您的构建说明中。评委将尽全力满足您的要求。

目标平台 - Linux

摘自 Clay 于 2007 年 11 月 15 日的博客,如果想要参与讨论,请点这里。

为了向那些希望深入了解评价平台的人们提供更多信息,我们将在下文中列举一些常见查询命令中出现的有关目标处理器及编译器软件的具体规范。(请注意:这些规范会随着硬件或软件的升级而有所更改,届时不会发出警告。)

[user17 ~]$ uname –a

Linux XXXXX-YY-ZZZZZZ 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:32:02 EDT 2006 x86_64 x86_64 x86_64 GNU/Linux

[user17 ~]$ g++ -v

Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix

--disable-checking --with-system-zlib --enable-__cxa_atexit

--disable-libunwind-exceptions --enable-java-awt=gtk

--host=x86_64-redhat-linux

Thread model: posix

gcc version 3.4.6 20060404 (Red Hat 3.4.6-3)

[user17 ~]$ icc –V

Intel(R) C Compiler for applications running on Intel(R) 64, Version 10.1 Build 20070913 Package ID: l_cc_p_10.1.008 Copyright (C) 1985-2007 Intel Corporation. All rights reserved.

[user17 ~]$ tail -n 24 /proc/cpuinfo

processor : 7

vendor_id : GenuineIntel

cpu family : 6

model : 15

model name : Genuine Intel(R) CPU @ 2.66GHz

stepping : 5

cpu MHz : 2666.723

cache size : 4096 KB

physical id : 1

siblings : 4

core id : 7

cpu cores : 4

fpu : yes

fpu_exception : yes

cpuid level : 10

wp : yes

flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm pni monitor ds_cpl est tm2 cx16 xtpr

bogomips : 5332.64

clflush size : 64

cache_alignment : 64

address sizes : 36 bits physical, 48 bits virtual

power management:

第10章排序自测题答案

第9章排序自测卷姓名班级 一、填空题(每空1分,共24分) 1. 大多数排序算法都有两个基本的操作:比较和移动。 2. 在对一组记录(54,38,96,23,15,72,60,45,83)进行直接插入排序时,当把第7个记录60插 入到有序表时,为寻找插入位置至少需比较6 次。 3. 在插入和选择排序中,若初始数据基本正序,则选用插入;若初始数据基本反序,则选用 选择。 4. 在堆排序和快速排序中,若初始记录接近正序或反序,则选用堆排序;若初始记录基本 无序,则最好选用快速排序。 5. 对于n个记录的集合进行冒泡排序,在最坏的情况下所需要的时间是O(n2) 。若对其进行快速 排序,在最坏的情况下所需要的时间是O(n2)。 6. 对于n个记录的集合进行归并排序,所需要的平均时间是O(nlog2n),所需要的附加空间 是O(n) 。 7.对于n个记录的表进行2路归并排序,整个归并排序需进行┌log2n┐趟(遍)。 8. 设要将序列(Q, H, C, Y, P, A, M, S, R, D, F, X)中的关键码按字母序的升序重新排列,则: 冒泡排序一趟扫描的结果是H C Q P A M S R D F X Y; 初始步长为4的希尔(shell)排序一趟的结果是P A C S Q H F X R D M Y ; 二路归并排序一趟扫描的结果是H Q C Y A P M S D R F X; 快速排序一趟扫描的结果是 F H C D P A M Q R S Y X; 堆排序初始建堆的结果是A D C R F Q M S Y P H X。 9. 在堆排序、快速排序和归并排序中, 若只从存储空间考虑,则应首先选取方法,其次选取快速排序方法,最后选取归并排序方法; 若只从排序结果的稳定性考虑,则应选取归并排序方法; 若只从平均情况下最快考虑,则应选取堆排序、快速排序和归并排序方法; 若只从最坏情况下最快并且要节省内存考虑,则应选取堆排序方法。 二、单项选择题(每小题1分,共18分) ( C )1.将5个不同的数据进行排序,至多需要比较次。 A. 8 B. 9 C. 10 D. 25 (C)2.排序方法中,从未排序序列中依次取出元素与已排序序列(初始时为空)中的元素进行比较,将其放入已排序序列的正确位置上的方法,称为 A. 希尔排序B. 冒泡排序C. 插入排序D. 选择排序(D)3.从未排序序列中挑选元素,并将其依次插入已排序序列(初始时为空)的一端的方法,称为

算法设计实验一归并排序(分治)和插入排序的比较分析

沈阳化工大学实验报告 课程名称算法设计与分析 项目名称归并排序(分治)和插入排序的比较 学院应用技术学院 专业计中职1401 指导教师张雪 报告人张庭浩学号 1422030125 实验时间 2016.11.05 提交时间 2016.11.05

一、实验目的 1.理解和掌握分治算法的相关内容。 2.具体完成插入排序和归并排序性能的比较。 二、实验内容 编写一个真随机函数,随机产生大量数字。在产生相同的一组大量随机数字后,分别用归并排序和插入排序两种算法进行排序,并通过时间函数分别计算出运行的时间。 三、伪代码 1.归并排序 /*数组a[]是原始数组,数组b[]是目标数组*/ 归并排序(数组a[],数组b[]){ `分割与归并(数组a[],0, a.length,数组b[]) } /*通过递归把要排序的子序列分的足够小*/ 分割与归并(数组a[],起始位置,结束位置,数组b[]){ if(结束位置- 起始位置< 2) 返回 中间位置= (起始位置+结束位置)/2 分割与归并(数组a[],起始位置,中间位置,数组b[]) 分割与归并(数组a[],中间位置,结束位置,数组b[]) 归并(数组a[],起始位置,中间位置,结束位置,数组b[]) 拷贝(数组a[],起始位置,结束位置,数组b[]) } 归并(数组a[],起始位置,中间位置,结束位置,数组b[]){ i0 = 起始位置,i1 = 中间位置 for j = 起始位置到结束位置 if(i0 < 中间位置且(i1 > 结束位置或a[i0] <= a[i1]){ //当i0没有超过中间位置时,有两种情况要将a[i0]复制到b[j]上: //1.i1已经超过结束位置,只要把剩下的复制过来就好; //2.a[i0]比a[i1]小 b[j]=a[i0] i0++ } else { b[j]=a[i1] i1++ } }

C (++)内部排序汇总(快速排序&冒泡排序&堆排序&选择排序&插入排序&归并排序)

#include #include #include #include #define M 30001 random(int a[30001]) { int i; for(i=1;i<30001;i++) a[i]=rand()%30001; }//随机生成30000个数函数 int change1(char a[81]) { int b=0,n,i; for(i=0;a[i]!=0;i++); n=i-1; for(;i>1;i--) b+=((int)pow(10,n+1-i))*(a[i-1]-48); if(a[0]=='-') b=b*(-1); else b+=((int)pow(10,n))*(a[0]-48); return b; }//字符转化成整型 insort(int a[30001]) { int i,j,temp,temp1,n; int count=0; n=30001; for(i=1;i=0;j--)/* 每次循环完毕数组的0到i-1项为一个有序的序列*/ { count=0;/*这里count是标记位,可以减少比较次数*/ if(a[j]>temp) { temp1=a[j+1]; a[j+1]=a[j]; a[j]=temp1;

count++; }//满足条件,前移 if(count==0) break;//位置恰当,退出 } } }//insort插入排序函数 selsort(int a[30001]) { int i,j,temp; for(i=1;i<30000;i++) for(j=i+1;j<30001;j++) if(a[i]>a[j]) { temp=a[j]; a[j]=a[i]; a[i]=temp; } }//选择排序 bubsort(int a[30001]) { int i,j,temp; for(i=1;i<30001;i++) for(j=30000;j>i;j--) { if(a[j-1]>a[j]) { temp=a[j-1]; a[j-1]=a[j]; a[j]=temp; } } }//冒泡排序 int partition(int a[30001],int low,int high)

数据结构第九章排序习题与答案

习题九排序 一、单项选择题 1.下列内部排序算法中: A.快速排序 B.直接插入排序 C. 二路归并排序 D.简单选择排序 E. 起泡排序 F.堆排序 (1)其比较次数与序列初态无关的算法是() (2)不稳定的排序算法是() (3)在初始序列已基本有序(除去n 个元素中的某 k 个元素后即呈有序, k<

归并排序上机题

实验一归并排序 一、实验目的 (1)掌握归并排序算法的思想; (2)掌握归并排序算法的程序实现。 二、实验环境 Windows 2000以上版本的操作系统,运用java或C语言实现该算法。 三、实验内容 在main函数中定义数A[]={52,49,80,36,14,58,61,23,97},调用归并排序函数MergeSort对A[]中的数据进行排序,调试并观察排序过程。

C语言实现: 1.#include 2.typedef int RecType;//要排序元素类型 3.void Merge(RecType *R,int low,int m,int high) 4.{ 5.//将两个有序的子文件R[low..m)和R[m+1..high]归并成一个有序的子文件 R[low..high] 6.int i=low,j=m+1,p=0; //置初始值 7. RecType *R1; //R1是局部向量 8. R1=(RecType *)malloc((high-low+1)*sizeof(RecType)); 9.if(!R1) 10. { 11.return; //申请空间失败 12. } 13.while(i<=m&&j<=high) //两子文件非空时取其小者输出到R1[p]上 14. { 15. R1[p++]=(R[i]<=R[j])?R[i++]:R[j++]; 16. } 17.while(i<=m) //若第1个子文件非空,则复制剩余记录到R1中 18. { 19. R1[p++]=R[i++]; 20. } 21.while(j<=high) //若第2个子文件非空,则复制剩余记录到R1中 22. { 23. R1[p++]=R[j++]; 24. } 25.for(p=0,i=low;i<=high;p++,i++) 26. { 27. R[i]=R1[p]; //归并完成后将结果复制回R[low..high] 28. } 29.} 30.void MergeSort(RecType R[],int low,int high) 31.{ 32.//用分治法对R[low..high]进行二路归并排序 33.int mid; 34.if(low

简单的归并排序算法例子

import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; public class GuiBing { public static void main(String[] args) throws Exception { int datalength=1000000; GuiBing gui=new GuiBing(); int[] array1=gui.createArray(datalength); int[] array2=gui.createArray(datalength); Thread.sleep(20000); long startTime = System.nanoTime();//纳秒精度 long begin_freeMemory=Runtime.getRuntime().freeMemory(); int[] final_array=gui.guibing(array1,array2); boolean result=gui.testResult(final_array); long end_freeMemory=Runtime.getRuntime().freeMemory(); System.out.println("result===="+result); long estimatedTime = System.nanoTime() - startTime; System.out.println("elapsed time(纳秒精 度):"+estimatedTime/100000000.0); System.out.println("allocated memory:"+(begin_freeMemory-end_freeMemory)/1000.0+" KB"); Thread.sleep(20000); } /** * 显示数组的内容 * @param array */ private static void dispalyData(int[] array) { for(int i=0;i

归并排序实验报告

篇一:归并排序与快速排序实验报告 一、实验内容: 对二路归并排序和快速排序对于逆序的顺序数的排序时间复杂度比较。 二、所用算法的基本思想及复杂度分析: 1、归并排序 1)基本思想:运用分治法,其分治策略为: ①划分:将待排序列 r1,r2,……,rn划分为两个长度相等的子序列 r1,……,rn/2和rn/2+1,……,rn。 ②求解子问题:分别对这两个子序列进行排序,得到两个有序子序列。 ③合并:将这两个有序子序列合并成一个有序子序列。 2)复杂度分析: 二路归并排序的时间代价是o(nlog2n)。二路归并排序在合并过程中需要与原始记录序列同样数量的存储空间,因此其空间复杂性o(n)。 2、快速排序: 1)基本思想:运用分治法,其分治策略为: ①划分:选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列 r1……ri-1和ri+1……rn,轴值的位置i在划分的过程中确定,并且前一个子序列中记录的值均小于或等于轴值,后一个子序列中记录的值均大于或等于轴值。 ②求解子问题:分别对划分后的每一个子序列递归处理。 ③合并:由于对子序列r1……ri-1和ri+1……rn的排序是就地进行的,所以合并不需要执行任何操作。 2)复杂度分析: 快速排序在平均时间复杂性是o(nlog2n)。最坏的情况下是o(n^2)。 三、源程序及注释: 1、归并排序 #include<iostream> #include<fstream> #include windows.h using namespace std; void merge(int r[],int r1[],int s,int m,int t ) } int mergesort(int r[],int r1[],int s,int t) { } void main() int i=s; int j=m+1; int k=s; while(i<=m&&j<=t) {} if(i<=m)while(i<=m) r1[k++]=r[i++];//第一个没处理完,进行收尾if(r[i]<=r[j])r1[k++]=r[i++];//取r[i]和r[j]中较小的放入r1[k]中else r1[k++]=r[j++]; else while(j<=t) r1[k++]=r[j++];//第二个没处理完,进行收尾for(int l=0;l<k;l++) { } r[l]=r1[l];//将合并完成后的r1[]序列送回r[]中if(s==t)r1[s]=r[s]; else{int m; m=(s+t)/2; mergesort(r,r1,s,m);//归并排序前半个子序列 mergesort(r,r1,m+1,t); //归并排序后半个子序列 merge(r1,r,s,m,t);//合并两个已排序的子序列 }return 0; int a[100000]; int a1[10000];

归并排序算法实现 (迭代和递归)

归并排序算法实现(迭代和递归)\递归实现归并排序的原理如下: 递归分割: 递归到达底部后排序返回: 最终实现排序: #include void merge(int *array, int low, int center, int high) { if(low >= high) return; int m = center - low + 1; int n = high - center; int L[m], R[n]; for(int i=0; i R[j]) array[k] = R[j++]; else array[k] = L[i++];

} while(i #include

归并排序算法的基本思想及算法实现示例

归并排序算法的基本思想及算法实现示例 归并排序(Merge Sort)是利用"归并"技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。 两路归并算法 1、算法基本思路 设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1..high],先将它们合并到一个局部的暂存向量R1(相当于输出堆)中,待合并完成后将R1复制回R[low..high]中。 (1)合并过程 合并过程中,设置i,j和p三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较R[i]和R[j]的关键字,取关键字较小的记录复制到R1[p]中,然后将被复制记录的指针i或j加1,以及指向复制位置的指针p加1。 重复这一过程直至两个输入的子文件有一个已全部复制完毕(不妨称其为空),此时将另一非空的子文件中剩余记录依次复制到R1中即可。 (2)动态申请R1 实现时,R1是动态申请的,因为申请的空间可能很大,故须加入申请空间是否成功的处理。 2、归并算法 void Merge(SeqList R,int low,int m,int high) {//将两个有序的子文件R[low..m)和R[m+1..high]归并成一个有序的 //子文件R[low..high] int i=low,j=m+1,p=0;//置初始值 RecType *R1;//R1是局部向量,若p定义为此类型指针速度更快 R1=(ReeType *)malloc((high-low+1)*sizeof(RecType)); if(! R1) //申请空间失败 Error("Insufficient memory available!"); while(i<=m&&j<=high) //两子文件非空时取其小者输出到R1[p]上 R1[p++]=(R[i].key<=R[j].key)?R[i++]:R[j++]; while(i<=m) //若第1个子文件非空,则复制剩余记录到R1中 R1[p++]=R[i++]; while(j<=high) //若第2个子文件非空,则复制剩余记录到R1中 R1[p++]=R[j++]; for(p=0,i=low;i<=high;p++,i++) R=R1[p];//归并完成后将结果复制回R[low..high] } //Merge 归并排序 归并排序有两种实现方法:自底向上和自顶向下。

第8章排序练习题答案

第8章排序练习题答案 填空题 1. 大多数排序算法都有两个基本的操作:比较和移动。 2. 在对一组记录(54,38,96,23,15,72,60,45,83)进行直接插入排序时,当把第7个记录60插 入到有序表时,为寻找插入位置至少需比较 3 次。 3. 在插入和选择排序中,若初始数据基本正序,则选用插入;若初始数据基本反序,则选用 选择。 正序时两种方法移动次数均为0,但比较次数量级不同,插入法:n-1即O(n),选择法:O(n2) 反序时两种方法比较次数量级相同,均为O(n2),但移动次数不同,插入法:O(n2),选择法:3(n-1)即O(n) 4. 在堆排序和快速排序中,若初始记录接近正序或反序,则选用堆排序;若初始记录基本 无序,则最好选用快速排序。 5. 对于n个记录的集合进行冒泡排序,在最坏的情况下所需要的时间复杂度是O(n2) 。若对其进 行快速排序,在最坏的情况下所需要的时间复杂度是O(n2)。 6. 对于n个记录的集合进行归并排序,所需要的平均时间是O(nlog2n){ ,所需要的附加空间是O(n) 。 7.对于n个记录的表进行2路归并排序,整个归并排序需进行┌log2n┐趟(遍)。 8. 设要将序列(Q, H, C, Y, P, A, M, S, R, D, F, X)中的关键码按字母序的升序重新排列,则: 冒泡排序一趟扫描的结果是H C Q P A M S R D F X Y; 二路归并排序一趟扫描的结果是H Q C Y A P M S D R F X; 快速排序一趟扫描的结果是 F H C D P A M Q R S Y X; 堆排序初始建堆的结果是Y S X R P C M H Q D F A。(大根堆) 9. 在堆排序、快速排序和归并排序中, 若只从存储空间考虑,则应首先选取堆排序方法,其次选取快速排序方法,最后选取归并排序方法;若只从排序结果的稳定性考虑,则应选取归并排序方法; / 若只从平均情况下最快考虑,则应选取快速排序方法; 若只从最坏情况下最快并且要节省内存考虑,则应选取堆排序方法。

第13周内排序第5讲-归并排序

归并排序是多次将相邻两个或两个以上的有序表合并成一个新的有序表。 最简单的归并是将相邻两个有序的子表合并成一个有序的表,即二路归并排序。1 、归并的思路

一次二路归并:将两个位置相邻的记录有序子序列归并为一个记录的有序序列。有序 序列R [low..high] 有序子序列R [low..mid]有序子序列R [mid+1..high] R [low..high]

void Merge (RecType R[],int low,int mid,int high) {RecType *R1; int i=low,j=mid+1,k=0; //k 是R1的下标,i 、j 分别为第1、2段的下标 R1=(RecType *)malloc((high-low+1)*sizeof(RecType));while (i<=mid &&j<=high) if (R[i].key<=R[j].key)//将第1段中的记录放入R1中 {R1[k]=R[i];i++;k++;} else //将第2段中的记录放入R1中 {R1[k]=R[j];j++;k++;} Merge():一次二路归并,将两个相邻的有序子序列归并为一个有 序序列。 空间复杂度为O(high-low+1) 2、二路归并算法

while(i<=mid)//将第1段余下部分复制到R1 {R1[k]=R[i];i++;k++;} while(j<=high)//将第2段余下部分复制到R1 {R1[k]=R[j];j++;k++;} for(k=0,i=low;i<=high;k++,i++)//将R1复制回R中R[i]=R1[k]; free(R1); }

多种排序的并行算法(具体)

1 排序 排序是数据处理中经常使用的一种重要运算,如何进行排序,特别是如何进行高效的排序,是计算机应用中的重要课题。排序的对象一般是一组记录组成的文件,而记录则是由若干数据项组成,其中的一项可用来标志一个记录,称为关键字项,该数据项的值称为关键字。所谓排序,就是要整理文件中的记录,使得它按关键字递增(或递减)的次序排列起来。若给定的文件含有n个记录{R1,R2,…,R n},它们的关键字分别为{K1,K2,…,K n},要把这n个记录重新排列成为{R i1,R i2,…,R in},使得{K i1≥K i2≥…≥K in}(或{K i1≤K i2≤…≤K in})。 本章主要介绍了枚举排序、快速排序、PSRS排序算法以及它们的MPI编程实现。1.1 枚举排序 1.1.1 枚举排序及其串行算法 枚举排序(Enumeration Sort)是一种最简单的排序算法,通常也称为秩排序(Rank Sort)。该算法的具体思想是(假设按关键字递增排序),对每一个待排序的元素统计小于它的所有元素的个数,从而得到该元素最终处于序列中的位置。假定待排序的n个数存在a[1]…a[n]中。首先将a[1]与a[2]…a[n]比较,记录比其小的数的个数,令其为k,a[1]就被存入有序的数组b[1]…b[n]的b[k+1]位置上;然后将a[2]与a[1],a[3]…a[n]比较,记录比其小的数的个数,依此类推。这样的比较操作共n(n-1)次,所以串行秩排序的时间复杂度为O(n2)。 算法13.1 枚举排序串行算法 输入:a[1]…a[n] 输出:b[1]…b[n] Begin for i=1 to n do (1) k=1 (2) for j=1 to n do if a[i]>a[j] then k=k+1 end if end for (3) b[k]= a[i] end for End 1.1.2 枚举排序的并行算法 对该算法的并行化是很简单的,假设对一个长为n的输入序列使用n个处理器进行排序,只需是每个处理器负责完成对其中一个元素的定位,然后将所有的定位信息集中到主进程中,由主进程负责完成所有元素的最终排位。该并行算法描述如下: 算法13.2 枚举排序并行算法

归并排序分治策略的设计与实现

实验名称归并排序分治策略的设计与实现实验方案实验成绩实验日期实验室信息系统设计与仿真室I 实验操作 实验台号班级姓名实验结果 一、实验目的 1、熟悉分治法求解问题的抽象控制策略; 2、熟悉在顺序存储表示下求解分类问题的递归算法设计; 3、通过实例转换, 掌握分治法应用。 二、实验任务 ①从文件中读取数据信息; ②利用归并排序算法,进行排序; ③输出排序结果。 三、实验设计方案 1、结构体设计 用数组存放排序数据。 2、自定义函数设计 ①函数原型声明 int input(int A[]); //从文件读入待排序的数据 void merge(int A[],int low,int mid,int high); // 两个相邻有序数组的归并 void mergesort(int A[],int low,int high); // 归并排序 void input(int A[], int n); // 输出排序结果 ②两个相邻的有序子数组的合并 思路:从两个已排好序的子数组的首元素开始,依次比较大小,按从小到大的顺序存放在b[]数组中,然后转存到A[]数组中。 void merge(int A[],int low,int mid,int high) { int b[N]; int i,j,k = 0; int l = low; //已排序部分1的起始下标 int h = mid+1; //已排序部分2的起始下标 while(l <= mid && h <= high) //两个有序部分合并到b数组中 if(A[l] < A[h]) b[k++] = A[l++]; else

多路归并排序 外部排序算法

关于多路归并排序外部排序败者树技术积累2009-11-24 21:52:06 阅读453 评论0 字号:大中小 编程珠玑第一个case是有关一个技巧性解决外部排序问题的。问题很巧妙的解决了,但一开始提到的利用归并排序进行外部排序的算法仍值得仔细探究一下,毕竟本科时学的不是很深入。 先来看内部排序中最简单的2路归并排序算法。 算法核心操作是将一维数组中前后相邻的两个有序序列归并为一个有序序列,给定数组中序列界限i、m、n,用2个下标变量分别从i和j=m+1开始逐个往后处理,先比较,小的写到结果序列的当前遍历下标k中,相应下标自增继续比较直到某个序列的下标走到边界,再将另外一个序列的剩余元素拷贝到结果序列中。 算法可用递归或递推实现,从相邻的两两元素开始不断调用上面的核心操作组成较长有序序列直到完成整个序列。 算法进行一趟归并就得到一个局部有序的完整新序列,n个元素共需要log2n趟归并,每趟完成比较操作n次(1次得到序列的1个值),得到的新序列写到结果序列空间中,下一趟之前要先将结果序列复制一份到临时空间,下一趟归并在临时空间上进行。因此时间复杂度nlog2n,空间上除了原始序列空间n、结果序列空间n,还需要辅助临时空间n。 接下来看外部排序。外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行多路归并排序。 多路归并排序算法在常见数据结构书中都有涉及。从2路到多路(k路),增大k可以减少外存信息读写时间,但k个归并段中选取最小的记录需要比较k-1次,为得到u个记录的一个有序段共需要(u-1)(k-1)次,若归并趟数为s次,那么对n个记录的文件进行外排时,内部归并过程中进行的总的比较次数为s(n-1)(k-1),也即(向上取整)(logkm)(k-1)(n-1)=(向上取整)(log2m/log2k)(k-1)(n-1),而(k-1)/log2k随k增而增因此内部归并时间随k增长而增长了,抵消了外存读写减少的时间,这样做不行,由此引出了“败者树”tree of loser的使用。在内部归并过程中利用败者树将k个归并段中选取最小记录比较的次数降为(向上取整)(log2k)次使总比较次数为(向上取整)(log2m)(n-1),与k无关。 败者树是完全二叉树,因此数据结构可以采用一维数组。其元素个数为k个叶子结点、k-1个比较结点、1个冠军结点共2k个。ls[0]为冠军结点,ls[1]--ls[k-1]为比较结点,ls[k]--ls[2k-1]为叶子结点(同时用另外一个指针索引b[0]--b[k-1]指向)。另外bk为一个附加的辅助空间,不属于败者树,初始化时存着MINKEY的值。 多路归并排序算法的过程大致为:首先将k个归并段中的首元素关键字依次存入

数据结构课程设计_排序算法比较【完整版】

课程设计报告 数据结构课程设计题目:各种排序 学生姓名:高扬 专业:网络工程 班级:10211302 学号:1021130221 指导教师:姜林王志波 2012年6 月27 日

目录 排序算法比较 一、程序要求分析 二、程序主要功能 三、程序运行平台 四、程序数据结构 五、算法及时间复杂度 六、程序源代码 七、自我总结

各种排序 一、需求分析 任务:用程序实现插入法排序、起泡法、选择法、快速法、合并法排序; 输入的数据形式为任何一个正整数,大小不限。 输出的形式:数字大小逐个递增的数列。 要求给出多组不同元素个数的输入数据,并用列表打印出每种排序下的各趟排序结果。每个排序法结束时应打印出其元素比较的次数和交换的次数。此程序需将结果用列表打印,一定要将其打印结果排列好。 二、程序的主要功能 1.用户输入任意个数,产生相应数量的随机数 2.用户可以自己选择排序方式(直接插入排序,冒泡排序、快速排序、选择排序、二路归并排序五种排序方法)的一种 3.程序给出原始数据、排序后从小到大的数据,并给出排序所用的时间,比较的总次数和交换的总次数。 三、程序运行平台 Visual C++ 6.0版本 四、数据结构 1.类: NuovSort{ public: void Myface(); void choose(); void insertsort(int R[],int n); //直接插入排序法 void Bubblesort(int R[],int n); //冒泡排序算法实现 void quicksort(int R[],int left,int right); //快速排序算法实现 void selectsort(int R[],int n); //直接选择排序算法实现

数据结构课程设计二路归并排序说明书

前言 1.1排序的重要性 生活中,无时不刻不充满这排序,比如:班级同学的成绩排名问题,公司产值高低的问题等等,解决这些问题的过程中,都涉及到了一个数据结构的构造思想过程。数据结构中的排序,也有很多种,如:插入排序、交换排序、选择排序等等,此时我们就要注意选择具有优解的算法,将一个数据元素(或记录)的任意序列,重新排列成一个有序的排列,便于我们查找。 假设含有n个记录的序列为{R1,R2,Rn},其相应的关键字序列为{K1,K2,…,Kn}需确定1,2…n的一种排序P1,P2…Pn,使其相应的关键字满足如下的非递减的关系:Kp1≤Kp2≤…≤Kpn,即按关键字{Rp1,Rp2,…,Rpn}有序的排列,这样的一种操作称为排序。一般情况下,排序又分为内部排序和外部排序。而在内部排序中又含有很多排序方法,就其全面性能而言,很难提出一种被认为是最好的方法,因为每一种方法都有它的优缺点,适合在不同的环境下使用。我们学习的排序有:直接插入排序、折半插入排序、希尔排序、快速排序、基数排序、归并排序等。本次课题研究中,我主要进行了二路归并排序的研究和学习。 1.2设计的背景和意义 排序是计算机领域的一类非常重要的问题,计算机在出来数据的过程中,有25%的时间花在了排序上,有许多的计算机设备,排序用去计算机处理数据时间的一半以上,这对于提高计算机的运行速度有一定的影响。此时排序算法的高效率显得尤为重要。 在排序算法汇中,归并排序(Merging sort)是与插入排序、交换排序、选择排序不同的另一类排序方法。归并的含义是将两个或两个以上的有序表组合成一个新的有序表。归并排序可分为多路归并排序,两路归并排序,既可用于内排序,也可以用于外排序。这里仅对内排序的两路归并排序进行讨论。 而我们这里所探究学习的二路归并排序,设计思路更加清晰、明了,程序本身也不像堆结构那样复杂,同时时间复杂度仅为0(N),同时在处理大规模归并排序的时候,排序速度也明显优于冒泡法等一些排序算法,提高排序算法的效率。 正文 2.1设计内容 设计一个利用二路归并算法实现的排序算法,针对输入的一组无序的数,利用栈或者数组机芯存储,然后进行数据的两两分组、比较,构造新的栈或者数组,依次类推,直到得到一个有序数组或者栈,最后输出有序数据,得到有序数据。 2.2设计要求 假设初始序列含有n 个数据(n是已经确定的数据个数),首先把n 个记录看成n

数据结构实验-归并排序算法

大连理工大学实验预习报告 学院(系):电信专业:班级: 姓名:学号:组:___ 实验时间:实验室:实验台: 指导教师签字:成绩: 实验名称Merge sort 一、实验目的和要求 (一)、实验目的 Design the merge sort algorithm and implement it in C language 设计归并排序算法并于C语言实现。 (二)、实验要求 Requirements: 1) Analyze the time complexity of your algorithm 2) Submit the document explaining your algorithm as well as the source code. 要求: 1)分析算法的时间复杂度。 2) 提交的文档中说明你的算法和源代码。 二、实验原理 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可 解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了? 可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。

并行归并排序

串行归并与并行归并排序算法 一、串行归并排序算法 归并排序是一种很容易进行并行化的算法,因为归并的各个数据区间都是独立的,没有依赖关系。并且归并排序是一种速度比较快的排序,且是一种稳定的排序算法,排序速度与关键词初始排列无关。 串行归并排序的算法大体的可以描述为:首先将要排序的表分成两个节点个数基本相等的子表,然后对每个子表进行排序,最后将排好序的两个子表合并成一个子表。在对子表进行排序时可以将子表再分解成两个节点数量基本相同的子表,当子表足够小时,也可以采用其他排序方法对子表进行排序,然后再对排好序的子表进行归并操作,最后将整个表排好序。 1、1算法流程图 并行归并排序算法的流程图: 串行归并排序算发流程图

1、2代码分析 #include using namespace std; #define N 11 int array[N] = { 4, 67, 456, 23, 1, 78, 26, 222, 34, 432, 12 }; //待排序数组int other[N]; //辅助空间,用以暂存已经排序的数组元素 void Swap(int &a, int &b) { int tmp = a; a = b; b = tmp; } /* array 待排序数组 * begin 数组开始的下标 * end 数组最后一个元素的下标 */ void MergeSort(int *array, int begin, int end) { if(end-begin+1 > 2) { MergeSort(array, begin, (end+begin)/2); MergeSort(array, (end+begin)/2+1, end); int i = begin, j = (end+begin)/2+1, k=begin; while(i<=(begin+end)/2 && j<=end) { if(array[i] < array[j]) other[k++] = array[i++]; else other[k++] = array[j++]; } while(i <= (begin+end)/2) other[k++] = array[i++]; while(j <= end) other[k++] = array[j++]; for(k=begin; k<=end; ++k) array[k] = other[k]; } else

归并排序算法论文

归并排序算法解决排序问题 目录 1引言 (2) 2.归并排序的基本思想 (2) 3.归并排序算法不同的方式 (3) 1.归并排序基本算法 (3) 1.实现过程 (3) 2.性能分析: (4) 2.递归二路归并排序 (5) 1.算法过程 (5) 2.性能分析: (6) 3.归并排序算法的改进算法 (7) 1.引理 (7) 2.应用例子 (7) 3.时间复杂性的分析 (8) 4.总结 (9) 5.参考文献 (9)

1引言 从归并排序的概念上进行分析,该算法的思想比较容易理解,并且也能够直观的感知其实质是利用存储空间的归并。在实现的过程中,可以有多种方法,画出归并过程示意图后,随即可以得出其算法的代码。但是我们在利用递归思想实现归并排序的教学程中,一定要让学生分清是用递归还是用回归进行的归并,画出图形区分这两种不同的归并过程。通过这一环节,我们不但能够理解稳定的归并排序,而且还让学生认清递归和回归是解决这一问题两种不同的操作过程。 2.归并排序的基本思想 归并排序主要是二路归并排序,它的基本思想是:设n个数据,初始时把他们看成n 个长度为l的有序子数组,然后从第—个子数组开始,把相邻的子数组两两归并,得到n/2个长度为2的新的有序子数组(当n为奇数是最后—个新的有序子数组长度为1);对这些新的有序子数组再两两归并;如此重复,直到得到—个长度为n的有序数组为止”。归并排序有两种实现方法:自顶向下和自底向上,前者定义是自底向上,

3.归并排序算法不同的方式 1.归并排序基本算法 1.实现过程 当初次理解归并概念的时候,我们可以列举下列一组数据的归并过程。例如:70 83 100 65 10 32 7 65 9 第一次:【70 83】【65 100】【10 32】【7 65】【9】 第二次:【65 70 83 100】【7 10 32 65】【9】 第三次:【7 10 32 65 65 70 83 100】【9】 第四次:【7 9 10 32 65 65 70 83 100】 具体程序代码如下: 函数:void merge(int e[],int n) 形参说明:e是已知待排序的数组,n是数组中元素的个数,下标从0开始。void merge(int e[],int n) { int +p=(int+)malloc(Sizeof(int)+n);/*开辟一块实现交替归并空间*/ int len=l,f=0;/*len为归并单元宽度,f是一个标识,实现交替归并*/while(1en=n)s end=n一1; /*确定真正末下标位置*/ merg_step(e,a,f_s,f_s+len-1,s_end);/*实现将两个单元合并*/

相关文档
最新文档