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

分治法排序:原理与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.mzph.cn/news/762229.shtml

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

相关文章

Expert Prompting-引导LLM成为杰出专家

ExpertPrompting: Instructing Large Language Models to be Distinguished Experts 如果适当设计提示&#xff0c;对齐的大型语言模型&#xff08;LLM&#xff09;的回答质量可以显著提高。在本文中&#xff0c;我们提出了ExpertPrompting&#xff0c;以激发LLM作为杰出专家回…

运动想象 (MI) 迁移学习系列 (14) : EEGNet-Fine tuning

运动想象迁移学习系列:EEGNet-Fine tuning 0. 引言1. 主要贡献2. 提出的方法2.1 EEGNet框架2.2 微调 3. 实验结果3.1 各模型整体分类结果3.2 算法复杂度比较3.3 不同微调方法比较 4. 总结欢迎来稿 论文地址&#xff1a;https://www.nature.com/articles/s41598-021-99114-1#cit…

【算法训练营】周测4

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 如果需要答案代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 考题11-4 题目描述 输入格式 从标准输入读入数据。 输入第一行为两个正整…

将main打包成jar;idea打包main为jar包运行

将main打包成jar&#xff1b;idea打包main为jar包运行 适用场景&#xff1a;可以封装一些小工具。 配置jar Maven中添加 <packaging>jar</packaging>将其打包为jar。 设置运行入口main 编译jar 看到jar输出 运行效果&#xff1a; 其中&#xff0c;三方依赖也被…

【Unity】获取游戏对象或组件的常用方法

前言 在Unity开发过程中&#xff0c;我们经常需要获取组件&#xff0c;那么在Unity里如何获取组件呢&#xff1f; 一、获取游戏对象 1.GameObject.Find GameObject.Find 是通过物体的名称获取对象的 所以会遍历当前整个场景&#xff0c;效率较低 而且只能获取激活状态的物体…

pytorch多层感知机

目录 1. 多层感知机2. 多层感知机loss梯度推导3. pytorch示例 1. 多层感知机 有多个输入节点、多个中间节点和多个输出节点 2. 多层感知机loss梯度推导 3. pytorch示例

MySQL 字段定义时的属性设置

开发的时候第一步就是建表&#xff0c;在创建表的时候&#xff0c;我们需要定义表的字段&#xff0c;每个字段都有一些属性&#xff0c;比如说是否为空&#xff0c;是否允许有默认值&#xff0c;是不是逐渐等。 这些约束字段的属性&#xff0c;可以让字段的值更符合我们的预期&…

HCIP—BGP路由聚合

在大型网络中&#xff0c;路由条目通常多达成千上万条&#xff0c;甚至几十万条&#xff0c;这给路由设备带来的挑战是&#xff1a;如何存储并有效管理如此众多的路由信息&#xff1f; BGP是一种无类路由协议&#xff0c;支持CIDR、VLSM和路由聚合。路由聚合技术的使用…

[Linux开发工具]——gcc/g++的使用

Linux编译器——gcc/g的使用 一、快速认识gcc/g二、程序的翻译过程2.1 预处理&#xff08;.i文件&#xff09;2.2 编译&#xff08;.s文件&#xff09;2.3 汇编&#xff08;.o文件&#xff09;2.4 链接&#xff08;生成可执行文件或库文件&#xff09; 三、认识函数库3.1 静态库…

微调alpaca-lora遇到的一些问题

1、环境简介 环境&#xff1a; 系统&#xff1a;Ubuntu torch&#xff1a;2.2.1 python&#xff1a;3.10 gpu&#xff1a;V100 16g peft&#xff1a;0.9.0 使用PEFT中的lora方式微调llama-2-7b-hf&#xff0c;项目地址&#xff1a;alpaca-lora 2、混合精度训练Tensor相互计算会…

Jupyter Notebook介绍、安装及使用教程

Jupyter Notebook介绍、安装及使用教程 一、什么是Jupyter Notebook&#xff1f;简介组成部分网页应用文档Jupyter Notebook的主要特点 二、安装Jupyter Notebook先试用&#xff0c;再决定安装安装前提使用Anaconda安装使用pip命令安装 三、运行Jupyter Notebook帮助启动默认端…

macOS 通过 MacPorts 正确安装 MySQL 同时解决无法连接问题

如果你通过 sudo port install 命令正常安装了 MySQL&#xff0c;再通过 sudo port load 命令启动了 MySQL Server&#xff0c;此刻却发现使用 Navicat 之类的 GUI 软件无法连接&#xff0c;始终返回无法连接到 127.0.0.1 服务器。这是一个小坑&#xff0c;因为他默认使用了 So…

零代码编程:用kimichat将srt字幕文件进行批量转换合并

文件夹里面有多个srt字幕文件&#xff0c;借助kimichat可以很方便的对其进行批量合并。 在kimichat中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;写一个Python脚本&#xff0c;完成一个处理整理文档内容的任务&#xff0c;具体步骤如下&#xff1a; 打开文件…

更新数据库表中的数据

目录 update 加上各种限制条件 update update 表名set 列名1xx,列名2xx 指定更新某列数据如果不添加where子句,则为全列更新 也可以在原有基础上更新: 注意,mysql语法里不支持,必须是列名列名数值 加上各种限制条件 比如加上order by子句,where子句,limit等 这些条件对于up…

【FLOOD FILL专题】【蓝桥杯备考训练】:扫雷、动态网格、走迷宫、画图、山峰和山谷【已更新完成】

目录 1、扫雷&#xff08;Google Kickstart2014 Round C Problem A&#xff09; 2、动态网格&#xff08;Google Kickstart2015 Round D Problem A&#xff09; 3、走迷宫&#xff08;模板&#xff09; 4、画图&#xff08;第六次CCF计算机软件能力认证&#xff09; 5、山…

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(四)—— 过拟合和欠拟合

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 通过增加容量或提前停止来提高性能。 在深度学习中&#…

C#对于文件中的文件名判断问题

C#中对于文件名的判断问题&#xff0c;我们使用bool值进行值的传递&#xff0c;首先我们使用内置方法进行文件字符串匹配的bool值回传&#xff0c;我们打印出文件名以及相对应的bool&#xff0c;即可知道文件名是否真正生效 bool isHave fileName.Contains("Hello"…

代码学习记录22--回溯算法第三天

随想录日记part22 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.17 主要内容&#xff1a;今天主要是结合类型的题目加深对回溯算法的理解&#xff1a;1.组合总和;2.组合总和 ;3.分割回文串。 39. 组合总和 40.组合总和II131.分割回文串 Topic1组合总和 题…

【Node.js从基础到高级运用】十四、Node.js 错误处理与日志记录

引言 在这篇博客文章中&#xff0c;我们将深入探讨Node.js中的错误处理和日志记录的最佳实践。我们会了解如何在Node.js应用程序中有效地捕获和处理错误&#xff0c;并利用日志库如morgan来记录应用程序的活动和错误信息。 第1部分&#xff1a;Node.js中的错误处理 同步代码中…

Spring AI Embeddings 和 Vector 入门

在前面 Spring AI Chat 简单示例 中介绍了 Chat 的基本用法&#xff0c;本文在此基础&#xff08;主要是pom.xml&#xff09;上继续探索 Embedding 和 Vector。 官方文档&#xff1a; embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embedding…