分治法排序:原理与C语言实现

news2024/11/15 11:53:09

分治法排序:原理与C语言实现

  • 一、分治法与归并排序概述
  • 二、归并排序的C语言实现
  • 三、归并排序的性能分析
  • 四、归并排序的优化

在计算机科学中,分治法是一种解决问题的策略,它将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之,从而解决整个问题。这种方法在排序算法中得到了广泛应用,其中最具代表性的就是归并排序算法。

一、分治法与归并排序概述

归并排序是一种典型的分治思想的体现。它采用递归的方法,将待排序的序列不断划分为更小的子序列,直到子序列的长度为1(此时可以认为子序列已经有序),然后将这些有序的子序列合并成一个大的有序序列。

归并排序的主要步骤包括:

分解:将待排序的序列分解成若干个子序列,每个子序列的长度尽可能相等。
递归求解:对每个子序列进行归并排序,直到子序列长度为1。
合并:将排序好的子序列合并成一个有序的序列。
归并排序的时间复杂度为O(nlogn),其中n为待排序序列的长度。这是因为每次递归分解都会将序列长度减半,而合并操作的时间复杂度与序列长度成正比。因此,归并排序是一种非常高效的排序算法。
在这里插入图片描述
在这里插入图片描述

二、归并排序的C语言实现

下面是一个简单的归并排序算法的C语言实现:

c
#include <stdio.h>

// 合并两个有序数组
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

// 创建临时数组  
int L[n1], R[n2];  

// 拷贝数据到临时数组L[]和R[]  
for (i = 0; i < n1; i++)  
    L[i] = arr[l + i];  
for (j = 0; j < n2; j++)  
    R[j] = arr[m + 1 + j];  

// 合并临时数组回arr[l..r]  
i = 0;  
j = 0;  
k = l;  
while (i < n1 && j < n2) {  
    if (L[i] <= R[j]) {  
        arr[k] = L[i];  
        i++;  
    } else {  
        arr[k] = R[j];  
        j++;  
    }  
    k++;  
}  

// 拷贝L[]的剩余元素  
while (i < n1) {  
    arr[k] = L[i];  
    i++;  
    k++;  
}  

// 拷贝R[]的剩余元素  
while (j < n2) {  
    arr[k] = R[j];  
    j++;  
    k++;  
}  

}

// 归并排序函数
void mergeSort(int arr[], int l, int r) {
if (l < r) {
// 找到中间点
int m = l + (r - l) / 2;

    // 对左边子数组进行归并排序  
    mergeSort(arr, l, m);  

    // 对右边子数组进行归并排序  
    mergeSort(arr, m + 1, r);  

    // 合并两个已排序的子数组  
    merge(arr, l, m, r);  
}  

}

// 测试函数
int main() {
int arr[] = {12, 11, 13, 5, 6, 7};
int arr_size = sizeof(arr) / sizeof(arr[0]);

printf("Given array is \n");  
for (int i = 0; i < arr_size; i++)  
    printf("%d ", arr[i]);  

mergeSort(arr, 0, arr_size - 1);  

printf("\nSorted array is \n");  
for (int i = 0; i < arr_size; i++)  
    printf("%d ", arr[i]);  

return 0;  

}
这段代码首先定义了一个merge函数,用于合并两个已排序的子数组。然后,定义了一个mergeSort函数,用于递归地对子数组进行归并排序。最后,在main函数中,我们创建了一个待排序的数组,并调用mergeSort函数对其进行排序。排序完成后,我们打印出排序后的数组。
在这里插入图片描述

三、归并排序的性能分析

归并排序算法以其稳定的时间和空间性能在计算机科学中占据了一席之地。以下是关于归并排序的一些性能分析:

时间复杂度:

最好情况:O(nlogn)
最坏情况:O(nlogn)
平均情况:O(nlogn)
无论输入数据的顺序如何,归并排序的时间复杂度始终为O(nlogn)。这是因为归并排序总是会将数组拆分为尽可能均等的两部分,然后逐层合并,每一层的合并操作时间复杂度都是线性的,而层数为logn。

空间复杂度:

额外空间复杂度:O(n)
归并排序需要额外的空间来存储临时数组。在合并两个子数组时,需要创建一个与待排序数组等大的临时数组来存储数据。因此,归并排序的空间复杂度为O(n)。

稳定性:
归并排序是一种稳定的排序算法。稳定性意味着当两个元素的值相等时,它们在排序后的相对位置不会改变。归并排序在合并两个子数组时,会保留相等元素的原始顺序,从而保证了稳定性。

应用场景:
归并排序适用于需要稳定排序的场景,尤其是当数据量较大时。它也常用于外部排序,即当数据量太大以至于无法一次性加载到内存中时,归并排序可以分批处理数据,然后将有序的结果合并成一个完整的有序序列。

四、归并排序的优化

尽管归并排序的时间复杂度已经相当优秀,但在实际应用中,还可以通过一些优化来进一步提升性能:

非递归实现:
归并排序的递归实现虽然直观易懂,但在递归深度较大时,可能会导致函数调用栈的开销较大。为了避免这种开销,可以使用非递归(迭代)的方式来实现归并排序。非递归实现通常使用显式的栈结构来模拟递归过程。

二路归并改为多路归并:
传统的归并排序是二路归并,即将数组分成两部分进行归并。可以将二路归并扩展为多路归并,即每次将数组分成更多的部分进行归并。多路归并可以减少归并的次数,从而加快排序速度。但需要注意的是,多路归并会增加合并操作的复杂性。

减少辅助数组的使用:
在归并排序中,通常需要使用一个与原始数组等大的辅助数组来存储合并后的结果。为了减少空间开销,可以尝试使用一些技巧来减少辅助数组的使用。例如,在合并两个子数组时,可以先将左半部分的数据复制到辅助数组中,然后从右半部分开始向左半部分合并数据。这样,只需要一个额外的辅助数组即可完成合并操作。但需要注意的是,这种方法可能会增加数据复制的开销。

通过以上优化措施,可以进一步提升归并排序算法的性能和效率。不过,在实际应用中,需要根据具体的数据规模和要求来选择合适的优化策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1535750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据可视化实战(三)

图书销量情况对比 import pandas as pd import matplotlib.pyplot as plt # 读取Excel数据 dfpd.read_excel(mrbook.xlsx) df序号书号序号.1月份销量rate0B189.787569e1211月15060.31B199.787569e1222月1200-0.32B259.787569e1233月33050.63B219.787569e1244月66100.54NaNNaN5…

docker 进入容器内部命令

docker容器运行了&#xff0c;怎么进入容器内部查看内部的文件情况呢&#xff1f; 答&#xff1a;可以通过docker exec 的命令查看。 docker exec --help 可以查看命令介绍 &#xff1a; docker exec -it XXX /bin/bash XX为容器ID 进入容器内部 /bin/bash是需要添加的 不…

虚拟机扩展:虚拟机快照

虚拟机快照 在学习阶段我们无法避免的可能损坏Linux操作系统。如果损坏的话&#xff0c;重新安装一个Linux操作系统就会十分麻烦。 那我们就可以通过快照将当前虚拟机的状态保存下来&#xff0c;在以后系统损坏时通过快照恢复虚拟机到保存的状态。 制作并还原快照 在VMware …

学习人工智能:Attention Is All You Need-1-介绍;Transformer模型架构;编码器,解码器

Transformer模型是目前最成功的chatGPT&#xff0c;Sora&#xff0c;文心一言&#xff0c;LLama&#xff0c;Grok的基础模型。 《Attention Is All You Need》是一篇由Google DeepMind团队在2017年发表的论文&#xff0c;该论文提出了一种新的神经网络模型&#xff0c;即Trans…

001_measuretime_in_Matlab运行时间测量与时间复杂度分析

Matlab中测量时间 在使用Matalb时&#xff0c;经常需要考虑自己编写代码的效率。在这种情况下&#xff0c;我们需要测量程序运行的时间。Matlab提供了一些函数来测量程序运行的时间。 1. 函数简介 本文涵盖的函数包括&#xff1a; tic和toc函数cputime函数timeit函数 1.1 …

微信投票小程序源码系统:礼物道具投票盈利能力超强 带完整的安装代码包以及安装部署教程

近年来&#xff0c;微信小程序以其便捷性、轻量化等特点&#xff0c;迅速占据了移动应用市场的一席之地。投票小程序作为其中的一种应用类型&#xff0c;因其独特的互动性和社交性&#xff0c;成为了商家进行品牌宣传、活动推广的有力工具。然而&#xff0c;市场上的投票小程序…

【数据可视化】Echarts官方文档及常用组件

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. Echarts官方文档介绍3. ECharts基础架构及常用术语3.1 ECharts的基础架构3.2 ECharts的常用术语3.2.1 ECharts的基本名词3.2.2 ECharts的图表名词 4. 直角坐标系下的网格及坐标轴4.1 直角坐标系下的网格4.2…

训练svm并部署树莓派

训练svm并部署树莓派 开发环境1. 准备数据集2. 训练模型3. 部署模型开发环境 vscode python 3.8 用到的库: scikit-learn==1.3.2 pickle torch pandas matplotlib 1. 准备数据集 数据为xls文件,如下格式 2. 训练模型 文件结构 执行训练 python代码 import pickle &…

基于Spring Boot的研究生志愿填报辅助系统

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

代码随想录day28(1)二叉树:二叉搜索树中的插入操作(leetcode701)

题目要求&#xff1a;给定二叉搜索树&#xff08;BST&#xff09;的根节点和要插入树中的值&#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证&#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 思路&#xff1a;对于二叉搜索树来说&…

win10 chm文件打开空白怎么办 win10 chm文件打开空白解决办法

win10 chm文件打开空白怎么办 win10 chm文件打开空白解决办法 有的win10用户遇到chm文件在本地打开是正常的&#xff0c;但是一旦共享就会出现打开空白的情况&#xff0c;像这种情况怎么办呢&#xff1f;其实会出现这种情况基本是因为win10系统的安全防护功能&#xff0c;它…

verilog设计-CDC:单bit脉冲快时钟域到慢时钟域

一、前言 当单bit信号由快时钟域传递给慢时钟域时&#xff0c;快时钟域的异步信号最小可为快时钟信号的一个时钟周期脉冲&#xff0c;快时钟域的单时钟周期脉冲长度小于慢时钟域的时钟周期&#xff0c;很有可能该脉冲信号在慢时钟域的两个时钟上升沿之间&#xff0c;导致该脉冲…

MATLAB环境下基于振动信号的轴承状态监测和故障诊断

故障预测与健康管理PHM分为故障预测和健康管理与维修两部分&#xff0c;PHM首先借助传感器采集关键零部件的运行状态数据&#xff0c;如振动信号、温度图像、电流电压信号、声音信号及油液分析等&#xff0c;提取设备的运行监测指标&#xff0c;进而实现对设备关键零部件运行状…

C++面试宝典第36题:骑士游历

题目 在国际象棋的棋盘上,使一个骑士遍历所有的格子一遍且仅一遍。对于任意给定的顶点,输出一条符合上述要求的路径。骑士的走法和中国象棋的马的走法一样,走日。 解析 本题是一个经典的回溯搜索问题,具体来说是求解国际象棋棋盘上骑士的遍历问题,也称为骑士巡游问题(Kni…

新品发布 | Ftrans FIE文件安全导入导出系统

关于飞驰云联 飞驰云联是中国领先的数据安全传输解决方案提供商&#xff0c;长期专注于安全可控、性能卓越的数据传输技术和解决方案&#xff0c;公司产品和方案覆盖了跨网跨区域的数据安全交换、供应链数据安全传输、数据传输过程的防泄漏、FTP的增强和国产化替代、文件传输自…

SinoDB系统数据库

在SinoDB数据库的一个实例中&#xff0c;存在多个数据库&#xff0c;分为系统数据库和用户数据库。系统数据库在实例初始化时自动创建&#xff0c;存放实例级别上的监控信息、数据字典信息&#xff0c;用户能够访问而不能修改这些数据。用户数据库由用户根据需要创建&#xff0…

Ubuntu Desktop - lock screen (锁屏)

Ubuntu Desktop - lock screen [锁屏] 1. System Settings -> Security & Privacy (安全和隐私)2. System Settings -> Keyboard -> Shortcuts -> System3. LockReferences 1. System Settings -> Security & Privacy (安全和隐私) 使用 Putty 远程登录…

飞跃前端瓶颈:技术进阶指南精华篇

引言&#xff1a; 在互联网的快车道上&#xff0c;前端技术日新月异。对于前端工程师而言&#xff0c;技术水平达到一定高度后&#xff0c;往往会遭遇成长的天花板。本文将探讨如何识别并突破这些技术瓶颈&#xff0c;分享实用的进阶策略和实践案例。 一、技术等级概览&#xf…

WORD某一段格式调整,其他段落也调整

在编辑WORD文字格式时&#xff0c;有时候会出现WORD某一段格式调整&#xff0c;其他段落的格式直接就乱了&#xff0c;该如何修复&#xff1f; 答&#xff1a;问题的根源在于格式的自动更新&#xff0c;把自动更新前面的勾选框取消即可。

Google的MELON: 通过未定位图像重建精确3D模型的突破性算法

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…