精华内容
下载资源
问答
  • 排序算法中的归并排序(Merge Sort)是利用”归并”技术来进行排序归并是指将若干排序的子文件合并成一有序的文件。 一、实现原理: 1、算法基本思路 设两有序的子文件(相当于输入堆)放在同一向量中相邻的...
  • 归并排序对n元素进行递增排序

    千次阅读 2016-10-08 20:49:13
    空间复杂度:O(n) (用于存储有序子序列合并后有序序列) 稳定性:稳定 */ void Merge(int source[],int temp[],int start,int mid,int end) { int i = start;// i是第一段序列的下标 int j= mid + 1;// j是第
    #include<stdlib.h>
    #include<stdio.h>
    /*
    平均时间复杂度:O(nlog2n)
    空间复杂度:O(n)  (用于存储有序子序列合并后有序序列)
    稳定性:稳定
    */
     
    void Merge(int source[],int temp[],int start,int mid,int end)
    {
        int i = start;// i是第一段序列的下标
    	int j= mid + 1;// j是第二段序列的下标
    	int k = start;//k是临时的合并序列的下标
    
    	// 扫描第一段和第二段序列,直到有一个扫描结束
        while(i!=mid+1 && j!=end+1)
        {// 判断第一段和第二段取出的数哪个更小,将其存入临时合并序列,并继续向下扫描
            if(source[i]<source[j])
                temp[k++] = source[i++];
            else
                temp[k++] = source[j++];
        }
        while(i!=mid+1)
            temp[k++] = source[i++];// 若第一段序列还没扫描完,将其全部复制到临时合并序列
        while(j!=end+1)
            temp[k++] = source[j++];// 若第二段序列还没扫描完,将其全部复制到临时合并序列
        for(i=start;i<=end;i++)//把temp数组中的结果装回source数组中
            source[i] = temp[i];
    }
     
    //内部使用递归
    void MergeSort(int source[],int temp[],int start,int end)
    {
        int mid;
    	mid=(start+end)/2;
        if(start<end)
        {      
            MergeSort(source,temp,start,mid);//递归拆分左数组,直至数组元素个数为1
            MergeSort(source,temp,mid+1,end);//递归拆分右数组,直至数组元素个数为1
            Merge(source,temp,start,mid,end);//将左右两边有序的数组合并
        }
    }
     
    int main(int argc,char * argv[])
    {
        int a[5]={8,7,6,5,4};
    	int i,b[5] = {0};
        MergeSort(a,b,0,4);
        for(i=0;i<5;i++)
            printf("%d ",a[i]);
        printf("\n");
        return 0;
    }

    展开全文
  • n进行排序(空间复杂度O(1))

    千次阅读 2016-06-11 10:20:13
    题目:如何n进行排序,要求时间复杂度O(n),空间复杂度O(1) ? 思路分析: (1)关键:哈希表,空间复杂度O(1)中1的含义(只要是常量就可以) (2)在数字范围有限制的情况下,只需要用一数组记录...

    题目:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1) ?
    思路分析:
    (1)关键:哈希表,空间复杂度O(1)中1的含义(只要是常量就可以)
    (2)在数字范围有限制的情况下,只需要用一个数组记录每个数字出现次数就可以了。
    (3)假定你的数字范围在0到65535范围之内,定义一个数组count[65536](这个空间是常量,和n无关,所以是O(1) ),初值全部为0。
    假设待排序数组中有下面这些数字:
    100,200,300,119,0,6…
    那么对于每个数字,都做在count中记录一下:
    100 => count[100]++
    200 => count[200]++
    300 => count[300]++
    119 => count[119]++
    0 => count[0]++
    6 => count[6]++

    最后,遍历一遍待排序数组中的所有数字,就可得到0~65535每个数字的个数(在count数组中),然后再顺序遍历count数组,count[n] = m,则输出m个n,(比如说有count[3] = 2, 那么说明有2个数字3),依次输出,最后可得结果。第一次遍历是O(n),第二次遍历是O(1),为常量,所以最后的时间复杂度为O(n),而空间复杂度为O(1)。

    具体实现如下:

    #include <iostream>
    using namespace std;
    #define MAXSIZE 100
    
    void hashSort(int arr[],int len)
    {
        int max = arr[0];
        int min = arr[0];
        for (int i = 0; i < len; i++) // 找出待排序数组中的最大值和最小值
        {
            if(max <= arr[i])
                max = arr[i];
            if(min >= arr[i])
                min = arr[i];
        }
    
        int *hash = new int[max - min + 1]; // 根据最大值和最小值来动态创建一个新数组
    
        for (int i = 0; i < max - min + 1; i++) // 将新数组的元素全部初始化为0
            *(hash + i) = 0;
    
        for (int i = 0; i < len; i++) // 记录每个数出现的次数
            (*(hash+arr[i] - min))++;
    
        int j = 0;
        for (int i = 0; i < max - min + 1; i++)
        {
            while ((*(hash + i))--)// 出现k次,重复k次
                arr[j++] = i + min; // 新数组的每个下标位置存储的值,就是“该位置对应的下标的值”的“出现次数”。
        }
        delete [] hash;
    }
    
    
    int main(int argc, const char * argv[]) {
    
        int arr[] = {3,2,6,5,7,1,4,9,0,8};
        int len = sizeof(arr)/sizeof(int);
    
        hashSort(arr, len);
    
        for (int i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
    
        printf("\n");
        return 0;
    }

    注意点:
    int *hash = new int[max - min + 1];
    此处定义数组时,不能使用 int temp[max - min + 1];的形式,定义数组时不能用变量来指定数组长度,因为定义数组时,分配空间是需要一个固定的值,来确定你所申请的空间的大小。
    如 int n = 5;
    int a[n];
    这样使用,根据编译器的不同,编译可能会通过,但是那个n始终是个变量,若n的值改变,则数组大小也会改变,在对其使用的时候就会使用到数组以外的内容,对程序会造成隐患,所以一般是不能编译通过的。
    所以,只能固定的申请a[5];即数组长度必须在编译时就已确定。
    c++可以用new表达式动态分配数组和用delete [] 撤消,new表达式返回新分配数组的第一个元素的指针。
    参考文章:【100题】第四十九题 排序,要求时间复杂度O(n),空间复杂度O(1)

    展开全文
  • 解析在下面 2-4,10,23题目写的有点问题,应该是104,105 ...注意哦,人家问的不是时间...就一位,数也不多,直接桶排序最好,速度是线性的 x2-5: 用排除法很好做。。。至于为啥是快排我也不知道。。。...

    解析在下面

    2-4,10,23题目写的有点问题,应该是104,105

    解析:

    p1-1:

    注意哦,人家问的不是时间复杂度,而是归并趟数的数量级,应该是O(logN) 

    x2-2:

    空间复杂度就是O(N),因为需要开一个临时数组

    x2-4:

    就一位,个数也不多,直接桶排序最好,速度是线性的

    x2-5:

    用排除法很好做。。。至于为啥是快排我也不知道。。。

    x2-6:

    对于10TB的海量数据,数据不可能一次全部载入内存,传统的排序方法就不适用了,需要用到外排序的方法。外排序采用分治思想,即先对数据分块,对块内数据进行排序,然后采用归并排序的思想进行排序,得到数据的一个有序序列。

    x2-7:

    归并一般用于外排序,如果用于内排,而不用插入 这种简单排序,

    可能的原因也就只有c了。

    a肯定错

    b插入排序是不占空间的

    x2-8:

    这个很难

    插入排序、选择排序、起泡排序原本时间复杂度是O(n2),更换为链式存储后的时间复杂度还是O(n2)。希尔排序和堆排序都利用了顺序存储的随机访问特性(堆排序的这个特性体现在:取出最大堆的根节点后,更新堆的过程),而链式存储不支持这种性质,所以时间复杂度会增加,因此选D。

    x2-9:

    因为堆排序就是每次删除最大堆,并把它放在最后,其实这个过程有点像冒泡我觉得

    x2-10:

    同2-4:

    x2-11,12,13:

    第一步:以34为主元

    第二部,左边递归排序

    x2-15:

    这个很明显就是插入排序的特点

    x2-16:

    这个题很好!!!

    考查各排序算法的特点。
    解答本题要对不同排序算法的特点极为清楚。
    对于起泡排序和选择排序而言,每一趟过后都能确定一个元素的最终位置,而由题目中所说,前两个元素和后两个元素均不是最小或最大的两个元素并按序排列。
    (二路)归并排序,第一趟排序结束都可以得到若干个有序子序列,而此时的序列中并没有两两元素有序排列。
    插入排序在每趟排序结束后能保证前面的若干元素是有序的,而此时第二趟排序后,序列的前三个元素是有序的,符合其特点。故正确答案是B。

    x2-17:

    和上一题差不多,也可以用排除法分析,只能是快排

    x2-19:

    看表

    x2-21:

    归并排序用于都是O(NlogN)

    x2-22:

    看图

    x2-23:

    这个没有桶排序,但是只有一位,那就用它的升级版基数排序即可

    后面的不用看了

     

     

     

     

     

     

    1-1

    对N个记录进行归并排序,归并趟数的数量级是O(NlogN)。 (2分)

    T         F

    2-1

    对N个记录进行归并排序,归并趟数的数量级是: (1分)

    1. O(logN)
    2. O(N)
    3. O(NlogN)
    4. O(N​2​​)

    作者: DS课程组

    单位: 浙江大学

    2-2

    对N个记录进行归并排序,空间复杂度为: (1分)

    1. O(logN)
    2. O(N)
    3. O(NlogN)
    4. O(N​2​​)

    作者: DS课程组

    单位: 浙江大学

    2-3

    给出关键字序列{ 431, 56, 57, 46, 28, 7, 331, 33, 24, 63 },下面哪个选择是按次位优先(LSD)链式基数排序进行了一趟分配和收集的结果? (2分)

    1. →331→431→33→63→24→56→46→57→7→28
    2. →56→28→431→331→33→24→46→57→63→7
    3. →431→331→33→63→24→56→46→57→7→28
    4. →57→46→28→7→33→24→63→56→431→331

    作者: DS课程组

    单位: 浙江大学

    2-4

    输入10​5​​个只有一位数字的整数,可以用O(N)复杂度将其排序的算法是:(1分)

    1. 快速排序
    2. 插入排序
    3. 桶排序
    4. 希尔排序

    作者: 陈越

    单位: 浙江大学

    2-5

    数据序列{ 3, 1, 4, 11, 9, 16, 7, 28 }只能是下列哪种排序算法的两趟排序结果?(2分)

    1. 冒泡排序
    2. 快速排序
    3. 插入排序
    4. 堆排序

    作者: 陈越

    单位: 浙江大学

    2-6

    对10TB的数据文件进行排序,应使用的方法是:(1分)

    1. 希尔排序
    2. 堆排序
    3. 归并排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-7

    在内部排序时,若选择了归并排序而没有选择插入排序,则可能的理由是:(2分)

    1. 归并排序的程序代码更短
    2. 归并排序占用的空间更少
    3. 归并排序的运行效率更高
    1. 仅 2
    2. 仅 3
    3. 仅 1、2
    4. 仅 1、3

    作者: 考研试卷

    单位: 浙江大学

    2-8

    下列排序方法中,若将顺序村吃更换为链式存储,则算法的时间效率会降低的是:(2分)

    1.插入排序;2.选择排序;3.起泡排序;4.希尔排序;5.堆排序

    1. 仅1、2
    2. 仅2、3
    3. 仅3、4
    4. 仅4、5

    作者: 考研试卷

    单位: 浙江大学

    2-9

    { 12,9,11,8,7,4,5,13,23 }是下列哪种方法第二趟排序后的结果? (2分)

    1. 归并排序
    2. 堆排序
    3. 插入排序
    4. 基数排序

    作者: DS课程组

    单位: 浙江大学

    2-10

    输入10​4​​个只有一位数字的整数,可以用O(N)复杂度将其排序的算法是:(1分)

    1. 桶排序
    2. 快速排序
    3. 插入排序
    4. 希尔排序

    作者: 陈越

    单位: 浙江大学

    2-11

    将序列{ 2, 12, 16, 88, 5, 10, 34 }排序。若前2趟排序的结果如下:

    • 第1趟排序后:2, 12, 16, 10, 5, 34, 88
    • 第2趟排序后:2, 5, 10, 12, 16, 34, 88

    则可能的排序算法是:(2分)

    1. 冒泡排序
    2. 快速排序
    3. 归并排序
    4. 插入排序

    作者: 陈越

    单位: 浙江大学

    2-12

    将序列{ 2, 12, 16, 88, 5, 10, 34 }排序。若前2趟排序的结果如下:

    • 第1趟排序后:2, 12, 16, 10, 5, 34, 88
    • 第2趟排序后:2, 5, 10, 12, 16, 34, 88

    则可能的排序算法是:(2分)

    1. 冒泡排序
    2. 归并排序
    3. 插入排序
    4. 快速排序

    作者: 陈越

    单位: 浙江大学

    2-13

    将序列{ 2, 12, 16, 88, 5, 10, 34 }排序。若前2趟排序的结果如下:

    • 第1趟排序后:2, 12, 16, 10, 5, 34, 88
    • 第2趟排序后:2, 5, 10, 12, 16, 34, 88

    则可能的排序算法是:(2分)

    1. 冒泡排序
    2. 归并排序
    3. 快速排序
    4. 插入排序

    作者: 陈越

    单位: 浙江大学

    2-14

    在对N个元素进行排序时,基于比较的算法中,其“最坏时间复杂度”中最好的是: (1分)

    1. O(logN)
    2. O(N)
    3. O(NlogN)
    4. O(N​2​​)

    作者: DS课程组

    单位: 浙江大学

    2-15

    下列排序算法中,哪种算法可能出现:在最后一趟开始之前,所有的元素都不在其最终的位置上?(设待排元素个数N>2) (2分)

    1. 冒泡排序
    2. 插入排序
    3. 堆排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-16

    若数据元素序列{ 11,12,13,7,8,9,23,4,5 }是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是: (2分)

    1. 冒泡排序
    2. 选择排序
    3. 插入排序
    4. 归并排序

    作者: DS课程组

    单位: 浙江大学

    2-17

    数据序列{ 3,2,4,9,8,11,6,20 }只能是下列哪种排序算法的两趟排序结果? (2分)

    1. 冒泡排序
    2. 选择排序
    3. 插入排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-18

    对一组数据{ 2,12,16,88,5,10 }进行排序,若前三趟排序结果如下: 第一趟排序结果:2,12,16,5,10,88 第二趟排序结果:2,12,5,10,16,88 第三趟排序结果:2,5,10,12,16,88 则采用的排序方法可能是: (2分)

    1. 冒泡排序
    2. 希尔排序
    3. 归并排序
    4. 基数排序

    作者: DS课程组

    单位: 浙江大学

    2-19

    就排序算法所用的辅助空间而言,堆排序、快速排序、归并排序的关系是: (1分)

    1. 堆排序 < 归并排序 < 快速排序
    2. 堆排序 > 归并排序 > 快速排序
    3. 堆排序 < 快速排序 < 归并排序
    4. 堆排序 > 快速排序 > 归并排序

    作者: DS课程组

    单位: 浙江大学

    2-20

    下面四种排序算法中,稳定的算法是: (1分)

    1. 堆排序
    2. 希尔排序
    3. 归并排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-21

    在基于比较的排序算法中,哪种算法的最坏情况下的时间复杂度不高于O(NlogN)? (1分)

    1. 冒泡排序
    2. 归并排序
    3. 希尔排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-22

    下列排序算法中,时间复杂度不受数据初始状态影响,恒为O(NlogN)的是: (1分)

    1. 冒泡排序
    2. 直接选择排序
    3. 堆排序
    4. 快速排序

    作者: DS课程组

    单位: 浙江大学

    2-23

    输入10​5​​个只有一位数字的整数,可以用O(N)复杂度将其排序的算法是: (1分)

    1. 快速排序
    2. 插入排序
    3. 希尔排序
    4. 基数排序

    作者: DS课程组

    单位: 浙江大学

    2-24

    排序方法中,从未排序序列中依次取出元素与已排序序列中的元素进行比较,将其放入已排序序列的正确位置的方法称为: (1分)

    1. 插入排序
    2. 选择排序
    3. 快速排序
    4. 归并排序

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 归并排序(Merge Sort)是一种基于分治法的高速算法。

    归并排序(Merge Sort)是用分治策略(分治法)实现对n个元素进行排序的一种高速的、稳定的排序算法。

    在介绍归并排序之前,我们首先简单的认识一下分治法

    分治法

    基本思想:
    将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且原问题相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
    精髓:
    分——将问题分解为规模更小的子问题。
    治——将这些规模更小的子问题逐个击破。
    合——将已解决的子问题合并,最终得到原问题的解。

    在简单的了解过分治法之后,我们便开始介绍本文的“主角”——归并排序了。在正式介绍之前,再补充说明一下:归并排序是分治法的一个典型应用和完美体现,它是一种平衡的、简单的二分分治策略。

    归并排序

    基本思想:
    将原始数组A[0:n-1]中的元素分成两个大小大致相同的子数组:A[0:n/2]和A[n/2+1:n-1],分别对这两个子数组单独排序,然后将已排序的两个数组归并成一个含有n个元素的有序数组。(不断地进行二分,直至待排序数组中只剩下一个元素为止,然后不断合并两个排好序的数组段)
    稳定性:
    归并排序包括不相邻元素之间的比较,但并不会直接交换。在合并两个已排序数组时,如果遇到了相同元素,只要保证前半部分数组优先于后半部分数组,相同元素的顺序就不会颠倒。
    复杂度:
    时间复杂度:
    归并排序算法的时间复杂度为O(nlogn)。(logn即为log2n)
    解析如下:
    当n=1时:T(n)=O(1)
    当n>1时:T(n)=2T(n/2)+O(n)
    其中,O(1)代表仅仅是计算出子序列的中间位置需要的常数时间。
    2
    T(n/2)代表递归求解两个规模为n/2的子问题所需的时间。
    O(n)代表合并算法可以在O(n)时间内完成。(因合并处理中,由于两个待处理的序列(局部数组)都已经完成了排序,因此可以在O(n1+n2)->O(n)时间内完成,n1指前半部分序列的长度,n2指后半部分序列的长度)
    解T(n)=2T(n/2)+O(n)由递推求解得:
    T(n)=2xT(n/2x)+xO(n)
    当递推最终的规模为1时,n/2x=1,那么x=logn
    则T(n)=n
    T(1)+logn*O(n)=n+lognO(n)=O(nlogn)
    空间复杂度:
    程序中变量占用了一些辅助空间,这些辅助空间都是常数阶,每合并一次会分配一个适当大小的缓冲区,且在退出时释放。最多分配大小为n,所以空间复杂度为O(n)。
    递归调用占用的栈空间是递归树的深度logn

    在介绍完归并排序的基本思想、稳定性和复杂度之后,我们在看代码实现之前先看下图解了解一下。

    归并排序中遇到的下标(标记)
    left代表序列在数组中的下界
    mid代表下界和上界的中间位置(mid=(left+right)/2)
    right代表序列在数组中的上界

    在这里插入图片描述
    接下来我们举个例子来看一下当n为偶数的时候归并排序的过程以及合并操作过程的图解

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在看过图解之后,接下来就看下对应的代码实现:

    辅助合并函数Merge(A,left,mid,right),该函数将排好序列的两个子序列A[left:mid]和A[mid+1:right]进行合并。(整个算法的基础)

    void Merge(int A[], int left, int mid, int right)             //合并操作的代码实现
    {
    	int *B = new int[right - left + 1];                       //申请一个辅助数组B[],与传递过来的序列数组等长
    	//图中的三个辅助标记(工作指针)
    	int i = left;                                             //指向待排序子序列数组A[left:mid]中当前待比较的元素
    	int j = mid + 1;                                          //指向待排序子序列数组A[mid+1:right]中当前待比较的元素
    	int k = 0;                                                //k指向辅助数组B[]中待放置元素的位置
    
    	while (i <= mid && j <= right)                             //当i和j都指向未超过数组范围的时候
    	{                                                          //从小到大排序,将A[i]和A[j]中的较小元素放入B[]中
    		if (A[i] <= A[j])                                      //当前半部分数组A[left:mid]的值不大于后半部分数组A[mid+1:right]的值时,将前半部分数组辅助标记对应的值存入辅助数组中(具有稳定性)
    			B[k++] = A[i++];                                   //存入辅助数组B[]中,且与之对应的辅助标记后移
    		else                                                   //否则将后半部分辅助标记对应的值存入B[]中
    			B[k++] = A[j++];                                   //存入辅助数组且与之对应的辅助标记后移
    	}
    
    	while (i <= mid)                                           //对序列A[left:mid]剩余的部分依次进行处理,与图中的(5)对应
    		B[k++] = A[i++];                                       //将辅助标记对应的值存入辅助数组中且辅助标记后移
    
    	while (j <= right)                                         //对序列A[mid+1:right]剩余的部分依次进行处理
    		B[k++] = A[j++];                                       //将辅助标记对应的值存入辅助数组中且辅助标记后移  
    
    	for (i = left, k = 0; i <= right; i++)                     //将合并后的序列复制到原来的A[]序列
    		A[i] = B[k++];
    
    	delete[] B;                                                //释放动态创建的辅助数组空间
    }
    

    递归形式的归并排序函数MergeSort(A,left,right)
    1、将给定的包含n个元素的局部数组“分割”成两个局部数组。
    2、对两个局部数组分别执行归并排序。
    3、通过合并函数Merge(A,left,mid,right)将两个已排序完毕的局部数组“整合”成一个数组。

    //递归形式的归并排序算法
    void MergeSort(int A[], int left, int right)                   //归并排序
    {
    	if (left < right)                                          //当数组内的元素数大于1时进行二分操作,只有一个元素的时候,不作任何处理直接结束
    	{
    		int mid;
    		mid = (left + right) / 2;                              //计算中间位置
    		MergeSort(A, left, mid);                               //对数组A[left:mid]中的元素进行归并排序
    		MergeSort(A, mid + 1, right);                          //对数组A[mid+1:right]中的元素进行归并排序
    		Merge(A, left, mid, right);                            //进行合并操作
    	}
    }
    

    在了解完代码实现后,看下归并排序的代码实现的执行顺序(与图解的联系)
    在这里插入图片描述

    归并排序的改进

    1、在数组长度比较短的情况下不进行递归,而选择其他排序方案:如插入排序。
    2、归并过程中,可以用记录数组下标的方式代替申请新内存空间,从而避免A和辅助数组间的频繁数据移动。
    3、从分支策略的机制入手,容易消除算法中的递归:
    先将数组A中相邻元素两两配对。用合并算法将他们排序,构成n/2组长度为2的排好序的子数组段,再将他们排序成长度为4的排好序的子数组段。如此继续下去,直至整个数组排好序。

    //消去递归后的合并排序算法可描述如下:
    void Merge(ElemType C[], ElemType D[], int left, int mid, int right)                               //合并C[left:mid]和C[mid+1:right]到D[left:right]
    {
    	int i = left;
    	int j = mid + 1;
    	int k = left;
    
    	while (i <= left && j <= right)
    		if (C[i] <= C[j])
    			D[k++] = C[i++];
    		else
    			D[k++] = C[j++];
    
    	while (i <= mid)
    		D[k++] = C[i++];
    
    	while (j <= right)
    		D[k++] = C[j++];
    }
    
    void MergePass(ElemType X[], ElemType Y[], int s, int n)       //函数MergePass()用于合并排好序的相邻数组段,具体的合并算法由Merge()函数来实现
    {                                                              //合并大小为s的相邻子数组
    	int i = 0;         
    
    	while (i <= n - 2 * s)
    	{
    		Merge(X, Y, i, i + s - 1, i + 2 * s - 1);              //合并大小为s的相邻2段子数组
    		i = i + 2 * s;                                         //标记后移
    	}
    
    	if (i + s < n)                                              //剩下的元素个数小于2s
    		Merge(X, Y, i, i + s - 1, n - 1);
    	else
    		for (int j = i; j <= n - 1; j++)
    			Y[j] = X[j];
    }
    
    void MergeSort(ElemType A[], int n)
    {
    	ElemType *B = new ElemType[n];                          //动态申请一个辅助数组
    	int s = 1;
    	while (s < n)                                           //当数组A[]中的元素个数大于1时
    	{
    		MergePass(A, B, s, n);                              //合并到数组B
    		s += s;
    		MergePass(B, A, s, n);                              //合并到数组A
    		s += s;
    	}
    }
    

    例题

    题目描述

    利用归并排序法将包含n个整数的数列S按升序排序

    输入

    输入有两行:第一行输入一个正整数n,第二行输入n个整数

    输出

    输出排序完毕的数列S,相邻的元素之间空格隔开

    程序代码如下
    #include<iostream>
    #include<cstdlib>
    #define ElemType_I int
    
    using namespace std;
    
    void Merge(ElemType_I A[], ElemType_I left, ElemType_I mid, ElemType_I right)             //合并
    {
    	ElemType_I *B = new ElemType_I[right - left + 1];                                     //申请辅助数组
    	ElemType_I i = left;
    	ElemType_I j = mid + 1;
    	ElemType_I k = 0;
    
    	while (i <= mid && j <= right)
    		if (A[i] <= A[j])
    			B[k++] = A[i++];
    		else
    			B[k++] = A[j++];
    
    	while (i <= mid)
    		B[k++] = A[i++];
    
    	while (j <= right)
    		B[k++] = A[j++];
    
    	for (i = left, k = 0; i <= right; i++)
    		A[i] = B[k++];
    
    	delete[] B;
    }
    
    void MergeSort(ElemType_I A[], ElemType_I left, ElemType_I right)                             //递归形式的归并排序
    {
    	if (left < right)
    	{
    		ElemType_I mid;
    		mid = (left + right) / 2;
    		MergeSort(A, left, mid);
    		MergeSort(A, mid + 1, right);
    		Merge(A, left, mid, right);
    	}
    }
    
    int main()
    {
    	ElemType_I n;
    	cin >> n;
    	ElemType_I *A = new ElemType_I[n];
    	for (int i = 0; i < n; i++)
    		cin >> A[i];
    
    	MergeSort(A, 0, n - 1);                                          //调用归并排序              
    
    	for (int i = 0; i < n; i++)
    		cout << A[i] << " ";
    
    	cout << endl;
    	//system("pause");                                                        //输出暂停,头文件<cstdlib>
    
    	return 0;
    }
    
    程序运行结果如下

    在这里插入图片描述
    [注释1]:当n为奇数时的图解以及稳定性的图解与上述类似,因此就不再进行描述了。归并排序也可以将数组分成A[left:mid]和A[mid:right],其中left指局部数组的开头元素,right指局部数组末尾+1的元素,A[left:mid]包括left到mid(不包括mid),A[mid:right]包括mid到right(不包括right),但其代码实现和图解需要部分修改。
    [注释2]:基于关键字比较的排序算法的平均时间复杂度的下界为O(nlogn)

    展开全文
  • 归并排序(合并排序

    千次阅读 2016-03-27 21:52:42
    合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两或两以上的有序数据序列合并成一新的有序数据序列,因此它又叫归并算法。它的基本思想就是假设数组A有N元素,那么可以看成数组A是又N...
  • 排序算法可以单线程执行(适用于小文件),也可以多线程执行(适用于大文件,分隔排序后再归并); 使用了如下技术要点: 命令行参数 面向对象 字符串解析 文件读取,写入 多线程、线程池、队列、线程同步 文件归并...
  • 数据结构与算法:归并排序(合并排序)

    千次阅读 多人点赞 2020-05-11 20:38:18
    数据结构与算法:归并排序/合并排序概述:图解: 概述: List item 图解: 假设我们有这样一组数据 A[9] = {4,3,6,7,9,1,2},他在内存中这样排序
  • n数用归并排序

    千次阅读 2018-09-17 12:11:39
    #include&lt;iostream&gt; using namespace std; void merge(int a[],int s,int m,int e,int tmp[])//s为开始m为中间e为末尾tmp为额外存储空间  { int pb=0;int p1=s;int p2=m+1; ...a...
  • 逆序归并排序

    千次阅读 2018-10-21 16:15:02
    在这个问题中,你需要分析一个对n个不同数排序的算法。该算法主要通过交换相邻数直到序列有序(升序)。比如:对输入序列 9 1 0 5 4 经过一系列交换后变成有序序列 0 1 4 5 9 你的任务是计算将序列变成有序最少...
  • 假设初始序列有 n 个记录,首先把它看成是 n 长度为 1 的有序子序列 (归并项),先做两两归并,得到 n / 2 长度为 2 的归并项 (如果 n 为奇数,则最后一有序子序列的长度为1);再做两两归并,…...
  • 主要介绍了Java实现List快速去重并排序操作,结合实例形式较为详细的分析了Java针对list的遍历、去重、排序相关操作技巧与注意事项,需要的朋友可以参考下
  • 1) 排序 n 元素,元素为随机生成的长为1..32的字符串(字符串均为英文小写字母),n的取值为:2^2,2^5,2^8,2^11,2^14,2^17; 2) 算法:直接插入排序,堆排序归并排序,快速排序; 3) 字符串大小判断标准...
  • 它的原理是假设初始序列含有n个记录,则可以看成是n有序的子序列,每子序列的长度为1,然后两两归并,得到【n/2】长度为2或1的有序子序列;再两两归并,...,如此反复,直到得到一长度为n的有序序列为止,...
  • 自然归并排序java版

    2017-11-06 13:19:37
    自然合并的核心主要是一Pass函数,这函数中设置了一array数组,来存放每一组有序元素的起始元素的下标,最后再将最后一元素的下标+1存放为array数组的最后一元素,这样,在后面的合并实现中会显现出这样记录的...
  • 排序--归并排序

    2017-03-27 23:54:30
    归并排序是典型的分治算法的例子,即先使每子序列有序,再使子序列段间有序归并排序的时空复杂度1、归并排序的时间复杂度归并排序的平均时间性能O(nlogn) 。2、归并排序的空间复杂度归并排序的空间复杂度为:O(n)...
  • 排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一数据元素(或记录)的任意序列,重新排列成一关键字有序的序列。 排序就是把集合中的元素按照一定的次序排序在一起。一般来说有升序排列和降序...
  • 课程实验数据结果,C语言实现快排归并插入大顶堆。 内含5W-50W随机生成整数每隔5W数据量排序一次的时间记录,并进行了均值和方差的比较。
  •  //归并方法:把两有序子序列合并成一有序序列  public void merge(int[]a, int[]b,int left, int mid, int right){  //该方法的具体功能:把左子序列a[left:mid] 和 右子序列a[mid+1:right] 归并到 b[left:...
  • 所谓的归并,是将两或两以上的有序文件合并成为一新的有序文件,归并排序是把一有n个记录的无序文件看成是由n长度为1的有序子文件组成的文件,然后进行两两归并,如此重复,直至最后形成包含n个归并,得到...
  • 归并排序算法

    2021-01-12 10:17:42
    文章目录一、归并排序介绍归并排序的思想2.1 归并排序的基本思想2.2 归并的基本步骤三、归并排序的代码实现 一、归并排序介绍 归并排序(merge sorting)是利用归并的思想实现的排序方法,该算法采用经典的分治...
  • 归并排序(merge_sort)是按照记录在序列中的位置序列进行划分 快速排序(quick_sort)是按照记录的值序列进行划分 两者都是基于分治法,时间复杂度都相同 代码的解析 //归并排序模板 #include <iostream...
  • 归并排序(基于分治的思想,先分解再合并)   算法思想:先分解,然后两两归并,直到合成一新的有序表。   相关代码如下: // 归并排序:先分解再合并 void Merge_sort(int[] array, int left, int ...
  • 假设含n个记录的序列为{ R1, R2, …, Rn }其相应的关键字序列为 { K1,K2, …,Kn }。经过排序确定一种排列{ Rp1≤Rp2≤…≤Rpn},使得它们的关键码满足如下递增或递减的关系 Kp1≤ Kp2 ≤…≤ Kp...
  • 归并排序,合并有序列表,求逆序对个数 之所以将标题中三者放一起是因为它们有密不可分的关系. 合并有序列表 定义一空列表 li 用来存放排序后的值; 定义两 cursor lc 和 rc,分别指向左右列表的首部; 比较 lc 和 ...
  • 排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一数据元素(或记录)的...本文主要介绍快速排序算法和归并排序算法的基本概念、原理以及具体的实现方法,并这两种排序算法的时间复杂度进行分析。
  • 归并排序

    2020-02-07 15:58:20
    归并排序的基本原理为:将序列平分为两个子序列(如果序列为奇数2*i+1,则第一个子序列为i+1,第个子序列为i),分别对子序列进行排序,再将已经有序的子序列合并,得到完全有序的序...
  • 算法设计与分析的实验报告,比较归并排序与快速排序的时间差异,这里采用在一java程序中随机生成的任意数分别进行两种方法的排序记录各自的时间,最后得出结论。 本实验报告附代码以及详细解释
  • N个记录进行归并排序归并趟数的数量级是O(NlogN)。() [解析]归并的数量级在O(logN)? 每上下相邻的两层之间,从上层到下层的过程就是一趟归并 满二叉树深度为k的二叉树的最后一层结点数为2^k - 1 所以叶子数为N...
  • 假设初始序列有n个记录,则可看成是n有序的子序列,每序列长度为1,然后两两归并,得到长度为2或者是1的有序子序列;再两两归并,,,,如此重复,直到得到一长度为n的有序序列为止,这种排序方法称为2-路...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 195,341
精华内容 78,136
关键字:

对20个记录进行归并排序