文字描述

  假设初始序列有n个记录,则可看成是n个有序的字序列,每个字序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,…, 如此重复,直到得到一个长度为n的有序序列为止,这种排序方法称为2-路归并排序。

示意图

算法分析

  2-路归并排序的时间复杂度为nlogn;

  2-路归并排序需要至少同待排序序列同等大小的辅助空间;

  与快速排序和堆排序相比,归并排序最大特点就是,它是一种稳定的排序方法。

  在一般情况下,2-路归并排序,尤其是递归形式的,很少在内部排序中使用,一般用于外部排序,因为反复的自身函数的调用,容易引起栈溢出。

代码实现

 #include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
* double log2(double x); 以2为底的对数
* double ceil(double x); 取上整
* double floor(double x); 取下整
* double fabs(double x); 取绝对值
*/ #define DEBUG #define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b)) //定义顺序表中结点个数的最大值
#define MAXSIZE 100
//定义无穷大INF的值
#define INF 1000000 //定义结点中的关键字类型为int
typedef int KeyType;
//定义结点中除关键字外的附件信息为int
typedef char InfoType; //待排序的结点的结构体
typedef struct{
//结点中的关键字
KeyType key;
//结点中的除关键字外的附加信息
InfoType otherinfo;
}RedType; //顺序表的结构体
typedef struct{
//顺序表中待排序的结点
RedType r[MAXSIZE+];
//顺序表中待排序的结点个数
int length;
}SqList; //依次打印顺序表中结点的信息
void PrintList(SqList L){
int i = ;
printf("下标值:");
for(i=; i<=L.length; i++){
printf("[%d] ", i);
}
printf("\n关键字:");
for(i=; i<=L.length; i++){
if(EQ(L.r[i].key, INF)){
printf(" %-3c", '-');
}else{
printf(" %-3d", L.r[i].key);
}
}
printf("\n其他值:");
for(i=; i<=L.length; i++){
printf(" %-3c", L.r[i].otherinfo);
}
printf("\n\n");
return ;
} //将有序的SR[i,...,m]和SR[m+1,...,n]归并为有序的TR[i,...,n]
void Merge(RedType SR[], RedType TR[], int i, int m, int n)
{
int j = , k =;
//将SR中记录由小到大地归并到TR
for(j=m+, k=i; i<=m && j<=n; ++k){
if(LQ(SR[i].key, SR[j].key)){
TR[k] = SR[i++];
}else{
TR[k] = SR[j++];
}
}
//将剩余的SR[i,...,m]复制到TR
for(; i<=m; i++){
TR[k++] = SR[i];
}
//将剩余的SR[j,...,n]复制到TR
for(; j<=n; j++){
TR[k++] = SR[j];
}
} //将SR[s,...,t]归并排序为TR1[s,...,t]
void MSort(RedType SR[], RedType TR1[], int s, int t)
{
if(s == t){
TR1[s] = SR[s];
}else{
//将SR[s,...,t]平分为SR[s,...,m]和SR[m+1,...,t]
int m = (s+t)/;
RedType TR2[MAXSIZE+];
//递归地将SR[s,...,m]归并为有序的TR2[s,...,m]
MSort(SR, TR2, s, m);
//递归地将SR[m+1,...,t]归并为有序的TR2[m+1,...,t]
MSort(SR, TR2, m+, t);
//将TR2[s,...,m]和TR2[m+1,...,t]归并到TR1[s,...,t]
Merge(TR2, TR1, s, m, t);
}
} //对顺序表L作2-路归并排序
void MergeSort(SqList *L)
{
MSort(L->r, L->r, , L->length);
#ifdef DEBUG
printf("对该数据作2-路归并排序后:\n");
PrintList(*L);
#endif
} int main(int argc, char *argv[])
{
if(argc < ){
return -;
}
SqList L;
int i = ;
for(i=; i<argc; i++){
if(i>MAXSIZE)
break;
L.r[i].key = atoi(argv[i]);
L.r[i].otherinfo = 'a'+i-;
}
L.length = (i-);
L.r[].key = ;
L.r[].otherinfo = '';
printf("输入数据:\n");
PrintList(L);
//对顺序表L最2-路归并排序
MergeSort(&L);
return ;
}

2-路归并排序

运行

内部排序->归并排序->2-路归并排序的更多相关文章

  1. 有k个list列表, 各个list列表的元素是有序的,将这k个列表元素进行排序( 基于堆排序的K路归并排序)

    解题思路: 排序方法:多路归并排序 每次将n个list的头元素取出来,进行排序(堆排序),最小元素从堆中取出后,将其所在list的下一个元素 放入堆中,调整堆序列. 函数实现原型: void list ...

  2. 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较

    2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...

  3. 9, java数据结构和算法: 直接插入排序, 希尔排序, 简单选择排序, 堆排序, 冒泡排序,快速排序, 归并排序, 基数排序的分析和代码实现

    内部排序: 就是使用内存空间来排序 外部排序: 就是数据量很大,需要借助外部存储(文件)来排序. 直接上代码: package com.lvcai; public class Sort { publi ...

  4. C++:探究纯虚析构函数以及实现数组的高速排序与链表的归并排序

    C++:探究纯虚析构函数以及实现数组的高速排序与链表的归并排序 标签: 数据结构 数组 链表 高速排序 归并排序 抽象类 虚继承 by 小威威 1.介绍 本篇博文将通过课后作业的(15 C++ Hom ...

  5. 选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用

    1.问题来源 在刷题是遇到字符串相关问题中使用 strcmp()函数. 在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底. #include & ...

  6. 连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort)

    连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort) 1,起泡排序(bubble sort),大致有三种算法 基本版,全扫描. 提前终止版,如果发现前区里没有发生交换 ...

  7. Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。

    Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得 ...

  8. 七种机器内部排序的原理与C语言实现,并计算它们的比较次数与移动次数。

    内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 排序是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列.排序分为 ...

  9. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

随机推荐

  1. 【Linux高级驱动】平台设备驱动机制的编程流程与编译进内核

    [平台设备驱动机制的编程流程] [如何将驱动静态的编译进内核镜像] 1.添加资源(dev-led.c) 1.1:一般来说,系统习惯上将资源放在arch/arm/plat-samsung/目录中 cp ...

  2. 【Spring源码分析】Bean加载流程概览(转)

    转载自:https://www.cnblogs.com/xrq730/p/6285358.html 代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. ...

  3. Angular4学习笔记(十)- 组件间通信

    分类 父子组件通信 非父子组件通信 实现 父子 父子组件通信一般使用@Input和@Output即可实现,参考Angular4学习笔记(六)- Input和Output 通过Subject 代码如下: ...

  4. 【hadoop】 hdfs shell 命令交互

    1.put 本地文件上传至hdfs中 2. cat 查看内容 3. 删除文件,文件夹 4. ls 5. copyFromLocal 复制本地文件到HDFS , copyToLocal hdfs 复制到 ...

  5. PHP_CodeSniffer HG 服务端部署篇

    环境:CentOs 6.7 语言:PHP5.4 PHP_CodeSniffer: https://github.com/phpdragon/PHP_CodeSniffer 本地代码检测请查看该文章:h ...

  6. 延续(continuation)

    首先看下延续的定义: 续延是在运行中被暂停了的程序:即含有计算状态的单个函数型对象.当这个对象被求值时,就会在它上次停下来的地方重新启动之前保存下来的计算 在计算机科学和程序设计领域,延续是计算机程序 ...

  7. xrdp完美实现Windows远程访问Ubuntu 16.04

    前言: 在很多场景下,我们需要远程连接到Linux服务器(本文是Ubuntu),传统的连接主要分为两种. 第一种:通过SSH服务(使用xshell等工具)来远程访问,编写终端命令,不过这个是无界面的, ...

  8. Unity3D Shader 内置函数

    Intrinsic Functions (DirectX HLSL) The following table lists the intrinsic functions available in HL ...

  9. ASP.NET MVC与ASP.NET Web Form简单区别

    概论: Asp.net  微软 提供web开发框架或者技术.分Web Form和ASP.NET MVC.下面简单说明各自优缺点及使用场景. Web Form 优点: 1.支持丰富的服务器控件.如:Gr ...

  10. Django之Web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...