【算法基础】归并排序解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 归并排序是建立在归并操作上的一种有效,稳定的排序算法,它是采用分治法的一个非常典型的应用。将待排序数组分为两条线逐级拆分,将子序列进行排序,然后沿两条线逐级合并,得到完全有序序列。这种通过递归,层层合并的方法,称为归并。
​作者:[柒号华仔]

个人信条:星光不问赶路人,岁月不负有心人。

个人方向:专注于5G领域,同时兼顾其他网络协议,编解码协议,C/C++,linux等,感兴趣的小伙伴可以关注我,一起交流。


1. 归并排序介绍

1.1 定义

谈到归并我们需要先认识“分治”,顾名思义,分治即分而治之,一个问题很复杂,那么我们把问题拆分为简单点的小问题,将小问题继续拆分,最后所需面对的都是最小问题。将这些最小问题解决掉,一步步合并为大问题,最后实现整个问题的解决。

归并排序是建立在归并操作上的一种有效,稳定的排序算法,它是采用分治法的一个非常典型的应用。将待排序数组分为两条线逐级拆分,将子序列进行排序,然后沿两条线逐级合并,得到完全有序序列。这种通过递归,层层合并的方法,称为归并。

1.2 基本原理

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

  1. 将数组拆分两个等分数组,然后逐级往下进行等分拆分,直至成为长度为1的最小元素;
  2. 数组元素两两进行排序,这些两两排序的元素归并为新的子数组;这里两个归并起点有两个点,一个是初始数组首元素,一个是等分初始数组中间元素。
  3. 前后两个子数组进行排序合并,形成更大的子数组;
  4. 依次向上排序和合并,直至两条线均合并为一个有序数组;
  5. 将两个支线数组进行合并,得到最终的有序数组。

1.3 时间复杂度

假设数组元素个数为n,时间复杂度为T(n),
将 n 个数的序列,分为两个 n/2 的序列,则:T(n) = 2T(n/2) + n
将 n/2 个数的序列,分为四个 n/4 的序列,则:T(n) = 4T(n/4) + 2n
将 n/4 个数的序列,分为八个 n/8 的序列,则:T(n) = 8T(n/8) + 3n

将 n/2k 个数的序列,分为2k个 n/2k 的序列,则:T(n) = 2kT(n/2k) + kn

当 T(n/2k) = T(1)时, 即n/2k = 1,转换为以2为底n的对数:k = log2n,把k带入到T(n)中,得:T(n) = n + nlog2n。

因此归并排序的时间复杂度就是O(nlogn)。

2. 代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void Merge(int* arr, int left, int right, int mid)
{
    int *p = (int*)malloc((right - left + 1) * sizeof(int));
    int *temp = p;
    int L = left;
    int R = mid + 1;
        memset(p, 0, (right - left + 1) * sizeof(int));
        
    while((L <= mid)&&(R <= right))
    {
        *p++ = arr[L] < arr[R]?arr[L++] : arr[R++];
    }
    while (L <= mid)
    {
        *p++ = arr[L++];
    }
    while (R <= right)
    {
        *p++ = arr[R++];
    }
 
    memcpy(arr + left, temp, (right - left + 1) * sizeof(int));
 
    free(temp);
}
 
void MergeSort(int* arr, int left, int right)
{
    if (left >= right)
        return;
    int mid = (left + right)/2;
 
    MergeSort(arr, left, mid);            
    MergeSort(arr, mid + 1, right);        
    Merge(arr, left, right, mid);    
}
 
int main()
{
    int arr[10] = { 3,6,9,2,1,4,8,7,5,10};
    MergeSort(arr, 0, 9);
 
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", arr[i]);
    }
 
    return 0;
}

运行结果:

image.png

相关文章
|
2天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
27天前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
140 30
|
6天前
|
存储 监控 算法
企业内网监控系统中基于哈希表的 C# 算法解析
在企业内网监控系统中,哈希表作为一种高效的数据结构,能够快速处理大量网络连接和用户操作记录,确保网络安全与效率。通过C#代码示例展示了如何使用哈希表存储和管理用户的登录时间、访问IP及操作行为等信息,实现快速的查找、插入和删除操作。哈希表的应用显著提升了系统的实时性和准确性,尽管存在哈希冲突等问题,但通过合理设计哈希函数和冲突解决策略,可以确保系统稳定运行,为企业提供有力的安全保障。
|
1月前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
247 15
|
2月前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
75 4
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
86 2
|
3月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
87 0
|
3月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
68 0
|
9天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
9天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多