归并排序

简介:

博学,切问,近思--詹子知 (http://blog.csdn.net/zhiqiangzhan) 

       

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序算法以O(nlogn)最坏情形运行时间运行,而所使用的比较次数几乎是最优的。但它的一个显著问题就是需要额外的存储空间来辅助排序,空间复杂度是O(n)的,与quicksort和heapsort相比就逊色了不少,不过也可以实现空间复杂度为O(1)的归并排序,这将增加比较操作和交换操作的次数。归并排序可以使用在外部排序上:一般两路的外部排序是从源文件里读出内存大小的一块,然后在内存中排序,在放回文件里,这样生成若干文件。然后在从其中两个文件中读数据,按照merge的方式写到另一个文件中去。这一步根本用不到辅助空间。唯一可能用到辅助空间的地方是前面的一步,即将一块数据在内存中排序。

  

归并操作

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。

归并操作的工作原理如下:

1.     申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

2.    设定两个指针,最初位置分别为两个已经排序序列的起始位置

3.    比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

4.    重复步骤3直到某一指针达到序列尾

5.    将另一序列剩下的所有元素直接复制到合并序列尾

 

归并排序

并排序具体工作原理如下(假设序列共有n个元素):

1.     将序列每相邻两个数字进行归并操作(merge),形成floor(n / 2)个序列,排序后每个序列包含两个元素

2.    将上述序列再次归并,形成floor(n / 4)个序列,每个序列包含四个元素

3.    重复步骤2,直到所有元素排序完毕  

 

算法演示1 (非递归版本): 

#include<stdio.h>

#include<stdlib.h> 

void merge(int[], int[], int, int);

void mergeSort(int[], int); 

int main(void){

       int a[] = {26, 5, 37, 1, 61, 11, 59, 15, 48, 19};

       int i, len = 10;

       printf("source data is: ");

       for(i = 0; i < len; i++){

              printf("[%2d]", a[i]);

       }

       printf("/n");

       mergeSort(a, len);

       printf("/n");

       printf("after sort, the data is: ");

       for(i = 0; i < len; i++){

              printf("%4d", a[i]);

       }

       printf("/n");

       return 0;

} 

void display(int a[], int k, int n){  

       int i, count = 1;

       for(i = 1; i <= n; i++){

              if((i == n) && (i % (2 * k) != 0)){

                     printf("%4d]", a[i - 1]);

              }else{

                     if((i % (2 * k)) == 1){

                            printf("[%2d", a[i - 1]);

                     }else if(i % (2 * k) == 0){

                            printf("%4d]", a[i -1]);

                     }else{

                            printf("%4d", a[i - 1]);

                     }

              }    

       }

       printf("/n");

} 

void mergeSort(int a[], int n){

       int *t, k = 1;

       if((t = malloc(sizeof(int) * n)) == NULL){

              printf("allocate array space failure!");

              exit(1);

       }    

       while(k < n){

              merge(a, t, k, n);

              display(a, k, n);

              k <<= 1;

       }

       free(t);

} 

void merge(int src[], int dest[], int k, int n){

       int i, j;

       int s1 = 0, s2 = k, e1, e2;

       int m = 0;

       while(s1 + k < n){

              e1 = s2;

              e2 = (s2 + k < n) ? s2 + k : n;

              for(i = s1, j = s2; i < e1 && j < e2; m++){

                     if(src[i] <= src[j]){

                            dest[m] = src[i++];

                     }else{

                            dest[m] = src[j++];

                     }                  

              }

              while(i < e1){

                     dest[m++] = src[i++];

              }

              while(j < e2){

                     dest[m++] = src[j++];

              }

              s1 = e2;

              s2 = s1 + k;

       }

       for(i = 0; i < n; i++){

              src[i] = dest[i];

       }

} 

算法演示2(递归版本):

#include<stdio.h>

#include<stdlib.h>  

void merge(int a[], int l, int m, int r){

       int* t;

       int i = l, j = m + 1, k = 0;

       if((t = malloc(sizeof(int) * (r - l + 1))) == NULL){

              printf("Allocate memory failure!");

              exit(1);

       }

       while(i <= m && j <= r){

              if(a[i] > a[j]){

                     t[k++] = a[j++];

              }else{

                     t[k++] = a[i++];

              }

       }

       if(i > m){

              while(j <= r){

                     t[k++] = a[j++];

              }

       }else{

              while(i <= m){

                     t[k++] = a[i++];

              }

       }

       for(i = l, k = 0; i <= r; i++, k++){

              a[i] = t[k];

       }

       free(t);

}

void sort(int a[], int l, int r){

       int m;

       if(l < r){

              m = (l + r) / 2;      

              sort(a, l, m);

              sort(a, m + 1, r);

              merge(a, l, m, r);

       }

 

void mergeSort(int a[], int n){

       sort(a, 0, n-1);

}

 

目录
相关文章
|
人工智能 Windows
浪潮YuanChat发布:个人电脑秒变AI助手
【2月更文挑战第3天】浪潮YuanChat发布:个人电脑秒变AI助手
425 1
浪潮YuanChat发布:个人电脑秒变AI助手
|
弹性计算 监控 数据安全/隐私保护
阿里云ECS云监控界面
阿里云ECS云监控界面
1324 2
|
4月前
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
155 2
|
数据采集 搜索推荐 UED
异步渲染对 SEO 的影响及应对策略
【10月更文挑战第23天】异步渲染在提升用户体验和性能的同时,确实会给 SEO 带来一定的挑战。但通过合理运用预渲染、提供静态版本、设置爬虫抓取时间、优化页面结构和内容以及使用服务端渲染等策略,可以有效地解决这些问题,实现 SEO 和用户体验的双赢。在未来的网页开发中,我们需要更加注重异步渲染技术与 SEO 的协调发展,以适应不断变化的网络环境和用户需求。
|
Kubernetes Cloud Native API
云原生架构下微服务治理的深度探索与实践####
本文旨在深入剖析云原生环境下微服务治理的核心要素与最佳实践,通过实际案例分析,揭示高效、稳定的微服务架构设计原则及实施策略。在快速迭代的云计算领域,微服务架构以其高度解耦、灵活扩展的特性成为众多企业的首选。然而,伴随而来的服务间通信、故障隔离、配置管理等挑战亦不容忽视。本研究聚焦于云原生技术栈如何赋能微服务治理,涵盖容器编排(如Kubernetes)、服务网格(如Istio/Envoy)、API网关、分布式追踪系统等关键技术组件的应用与优化,为读者提供一套系统性的解决方案框架,助力企业在云端构建更加健壮、可维护的服务生态。 ####
|
人工智能
阿里数赛首次向AI开放!
【2月更文挑战第24天】阿里数赛首次向AI开放!
279 1
阿里数赛首次向AI开放!
|
存储 运维 算法
PolarDB-X 一致性共识协议 (X-Paxos)
近几年NewSQL和云原生数据库的不断兴起,极大地推动了关系数据库和一致性协议的结合,PolarDB-X也是在这样的背景下应运而生。
2257 0
PolarDB-X 一致性共识协议 (X-Paxos)
|
存储 运维 安全
导论|数据可信流通 从运维信任到技术信任
《数据二十条》提出建立数据可信流通体系,强调全流程合规与监管,确保数据来源合法、隐私保护和交易规范。数据已成为数字经济的关键要素,但面临身份确认、利益依赖、能力预期和行为后果的信任挑战。安全事件暴露了所有权保障和越权使用风险,外循环模式下责任主体不清、利益不一致等问题突显。为解决信任问题,需从运维信任转向技术信任,利用密码学和可信计算实现身份确认、利益对齐、能力预期和行为审计。关键技术包括可信数字身份验证、使用权跨域管控、安全分级测评和全链路审计。数据密态时代借助密码学保障数据全生命周期的安全可控,降低流通风险,实现广域数据的可信流通。基础设施如密态天空计算将支持这一转型。
318 0
|
安全 算法 C语言
|
SQL 关系型数据库 MySQL
数据库导入导出工具BatchTool介绍
本文将围绕 MySQL 以及 PolarDB-X 的数据离线导入导出场景来展开。首先,通过实验进行了生态工具 BatchTool 与传统 mysqldump 的性能对比,然后结合具体的实践场景来介绍 BatchTool 不同参数的使用方式。