算法分析——合并排序和快速排序

程序员面试必备——动画详解十大经典排序算法(C语言版) 博客原文地址 排序算法是程序员必备的基础知识,弄明白它们的原理和实现很有必要。本文中将通过非常细节的动画展示出算法的原理,配合代码更容易理解。 概述 由于待排序的元素数量不同,使得排序过程中涉及的存储器不同,可将排序方法分为两类:一类是内部排序,指的是待排序列存放在计算机随机存储器中进行的排序过程;另一类是外部排序,指的是待排序的元素的数量很大,以致内存一次不能容纳全部记录,在排序过程中尚需对... 阅读详情


前言

本文用于记录和总结算法学习中关于合并排序和快速排序的内容。合并排序和快速排序运用了分治策略来提高算法的效率,二者是如何体现分治思想,又有何异同呢?


一、分治法

在数学上,分治法是这样定义的:

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。

For example,给全班同学按照身高进行排队,我们可以依次让每一位同学都与已入列的同学进行比较再入列,这就是最简单的插入排序思想;如果运气好,所有同学的初始站位就是按照身高有序排列的,此时指针老师只需从头至尾地遍历一遍所有数据即可,时间复杂度为O(n)。反之,若整个序列散乱排列,那么每个数据都要进行n-1次比较,此时的时间复杂度为O(n^2),平均时间复杂度为O(n^2),算法效率非常低!

但是!如果你有幸学习了算法,就不难想到利用分治法的思想,先将同学们分成小组并进行组内排列,再将有序的子模块合并,再次进行组内排序;重复上述步骤,直至这个“模块”中包含了全班所有同学,即回到规模为N的问题中。

简言之,分治法就是将一个复杂问题“向下分解——求解——向上合并”的过程。

二、合并排序

1.基本思想

合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的,然后再把有序子序列合并为整体有序序列。

2.复杂度分析

合并排序是一个“对折”的操作过程,对n个元素进行排序,当n=1时终止排序,否则将待排序元素分成大小大致相同的两个子集合,分别对子集合进行排序,最终将排好序的子集合合并成所要求的集合。

总计算时间由合并时间和排序时间两部分组成,其中合并操作总能在O(n)时间内完成,所以在最坏情况下所需的时间T(n)满足:

T(n)=\left\{\begin{matrix}O(1),n \leqslant 1 \\ 2T(n/2)+O(n),n>1 \end{matrix}\right.

则,T(n)=O(n\log n)。

为便于理解,这里给出合并排序的算法描述:

template <class Type>
void MergeSort(Type a[],int n)
{
    Type new Type[n];
    int s=1;
    while(s<n){
        MergePass(a,b,s,n);//合并到数组b
        s+=s;
        MergePass(b,a,s,n);//合并到数组a
        s+=s;
    }
}

三、快速排序

1.基本思想

快速排序基于分治策略的另一个排序算法,其基本思想是在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。

2.复杂度分析

快速排序的运行时间与其划分是否对称有关,最坏情况是划分过程中产生的两个区域分别包含n-1个元素和1个元素,此时的T(n)满足:

T(n)=\left\{\begin{matrix}O(1),n\leq1 \\ T(n-1)+O(n),n>1 \end{matrix}\right.,

解递归方程可得T(n)=O(n^2)。

在最好情况下,每次划分所取的pivot都为中值,产生两个大小相同的区域。此时的T(n)满足:

T(n)=\left\{\begin{matrix}O(1),n\leq1 \\ 2T(n/2)+O(n),n>1 \end{matrix}\right.,

解得T(n)=O(n\log n)。并且,快速排序平均时间复杂度也是T(n)=O(n\log n)。

以下是快速排序的算法描述:

template <class Type>
void QuickSort(Type a[],int p, int r)
{
    if(p<r){
    int q=Partition(a,p,r);//划分数组
    QuickSort(a,p,q-1);//对左半端排序
    QuickSort(a,q+1,r);//对右半段排序
    }
}

由于划分是快速排序的关键,这里也将其代码附上:

template <class Type>
int Partition(Type a[],int p,int r)
{
    int i=p,j=r+1;
    Type x=a[p];
    while(1){
        while(a[++j]<x);
        while(a[--j]>x);
        if(i>=j) break;
        Swap(a[i],a[j]);
        }
    a[p]=a[j];
    a[j]=x;
    return j;
}

总结

合并排序和快速排序的时间复杂度虽然相同,但不难看出合并排序算法更加稳定。一般,我们通过随机生成快速排序的基准元素来降低轴偏移对算法性能的影响。

ACM基础题(二)  合并果子【问题描述】在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少, 阅读详情

相关推荐

QML 地图修改插件源码(三),Map在Plugin中设置加载地图类型

常用的地图种类分为交通图,地形图,卫星图等等,在QML的Map(以OSM地图为例)中提供activeMapType属性用于读取当前显示的地图类型(注意:该属性为只读属性,不能用于赋值),QML中地图的加载寻找根据瓦片的文件名进行查找,例如名为"osm_100-l-5-2-2-3.png"的瓦片,其中5代表了该地图的类型

zjgo007的专栏 3164

分治算法的经典案例——合并排序

一算法设计 合并排序是采用分治策略进行排序的算法,是分治算法的一个典型应用和完美体现。它是一种平衡、简单的二分分治策略。 算法步骤如下。 1分解 将待排序元素分成大小大致相同的两个子序列。 2治理 对两个子序列进行合并排序。 3合并 将排好序的有序子序列进行合并,得到最终的有序序列。 二算法图解 首先将待排序的元素分成大小大致相同的两个子序列,然后把子序列分成大小大致相同的两个子序列,如此下去,直到分解成一个元素为止,这时含有一个元素的子序列就是有序的;然后执行合并操作,将...

实践求真知 6161

逆向实战:TikTok X-Gorgon算法解析与Unidg补环境技巧

本文详细解析了TikTok X-Gorgon算法的逆向工程全流程,包括参数定位、变种RC4算法还原及Unidbg补环境技巧。通过动态调试与静态分析相结合,揭示了X-Gorgon的生成逻辑和加密细节,为移动安全研究提供了实用指南。

weixin_28568819的博客 693

分治法实现合并排序

实验目的 分治法实现合并排序,得到不同规模数据实验的时间对比,并进行时间复杂度分析。 实验原理 使用分治法,根据不同的输入用例n,准确输出这n个随机数从小到大排列后的序列。 合并排序算法思想:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。 实验步骤 ①创建两个数组。 ②不断将原数组从中间分开,然后放入两个数组中。 ③将两个数组中的元素逐一进行比较放入原数组中。 关键代码 //合并函数,q为切分点,array数组就是随机数的数组 vo

海棠的博客 2844

动态知识图谱构建:从本体论到工程实践

知识图谱作为语义网和人工智能领域的核心技术,旨在通过结构化的方式表示和组织知识。其核心原理在于将实体、概念及其关系建模为图结构,从而支持复杂的语义推理和关联查询。这一技术为机器理解数据间的深层联系提供了基础,在智能推荐、企业知识管理和学术研究等领域具有重要价值。通过结合自然语言处理(NLP)和图数据库技术,系统能够从非结构化数据中自动抽取知识,并构建动态演化的认知网络。本文以“本体论章鱼”项目为例,探讨了如何实现从静态本体到动态知识网络的范式转变,并详细解析了其分布式感知、适应性学习的架构设计,为构建灵活可

weixin_30731305的博客 657

别再只用固定线了!聊聊Android车机‘快速倒车’与‘正常倒车’的UI与数据流核心差异(附动态轨迹线实现原理)

本文深度解析Android车机中快速倒车与正常倒车的核心差异,探讨从内核级视频流水线到动态轨迹线的技术实现。快速倒车通过内核直接操作FrameBuffer实现2秒内响应,而正常倒车则支持多传感器数据融合与动态UI元素。文章还分享了动态轨迹线的算法实现与性能优化技巧,帮助开发者打造极致的倒车体验。

weixin_42550597的博客 253

分治法——合并排序(归并排序)

合并排序(归并排序) 合并排序是成功应用分治技术的一个完美例子。对于一个需要排序的数组A[0…n-1],合并排序把它一分为二:A[0..⌊n/2⌋−1]和A[⌊n/2⌋..n−1]A[0..\lfloor n/2 \rfloor -1]和A[\lfloor n/2 \rfloor ..n-1]A[0..⌊n/2⌋−1]和A[⌊n/2⌋..n−1],并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。对两个有序数组的合并(merging)可以通过merge的算法完成。初始状态下,两个指针(数

qq_53226437的博客 2076

VC Spyglass CDC实战:如何快速定位和解决重汇聚问题(附详细调试步骤)

本文深入探讨了在SoC设计中利用VC Spyglass进行CDC验证时,如何高效定位和解决棘手的重汇聚问题。通过实战演练,详细解析了重汇聚的本质、VC Spyglass的检测逻辑,并提供了从报告筛选、GUI原理图分析到制定设计修复或约束豁免方案的全套调试步骤,帮助工程师快速攻克这一常见验证难题。

weixin_29219539的博客 752

合并排序(归并排序 MergeSort)

合并排序(MergeSort)是一种采用分治法策略对一组无序数据进行排序的算法。 分治法:将原问题划分为n个规模较小而结构与原问题相似的子问题;递归的解决这些子问题,然后合并子问题的结果,就得到原问题的解。分治法在每一层递归上有3个步骤:分解、解决、合并。 分解(Divide):将原问题分解为一系列子问题。 解决(Conquer):递归的解各个子问题,若子问题足够小,...

指尖飞舞 1008

Retinanet训练自己的数据(2):模型准备

  在上一篇博客中,我们已经处理好了模型需要的数据集,下一步就是准备模型去训练数据。这里提醒一句,在制作数据时,最好将训练集和测试集人为分开。像Google tensorflow API,在制作数据时可以按比例自动生成,但是在上一篇文章中产生的数据(annotation.csv )其实都是用来训练的,如果你把自己的数据集全都转换了,那么恭喜你,最后你会发现没有数据集去测试了。   下面开始模型准...

mingyang_wang的博客 5884

活用QueryWrapper与@Select注解,构建MybatisPlus动态多表查询方案

本文深入探讨了如何结合MybatisPlus的QueryWrapper与@Select注解,构建高效灵活的动态多表关联查询方案。通过解析${ew.customSqlSegment}占位符机制,并设计通用的Service层封装,解决了复杂条件下多表查询的SQL拼接难题,显著提升了后台管理系统列表查询的开发效率与可维护性。

weixin_29291069的博客 271

【西南科技大学】算法分析 快速排序 合并排序

元素长度为n的归并排序所消耗的时间 T[n]:调用Sort()函数划分两部分,那每一小部分排序好所花时间则为 T[n/2],而最后把这两部分有序的数组合并成一个有序的数组,即merge(a,left,mid,right,temp)所花的时间为 O(n);这次实验让我更加理解分治的思想,对算法知识的运用更加熟练,我深刻明白了算法的重要性,程序的编写离不开它,而且可以培养我们的思维能力,培养我们的思考分析、解决问题的能力。④ 空间复杂度:主要是递归造成的栈空间的使用,最好情况,递归树的深度为log。

x24_my的博客 373

【深度学习新浪潮】李飞飞团队VAGEN框架深度解析:让VLM智能体学会“三思而后行“

VAGEN框架的真正价值,不仅在于性能指标的突破,更在于重新定义了VLM智能体的发展方向——人工智能的进步不应只追求"做得对",更要实现"想得清"。李飞飞团队通过强制显式思考、动态表示适配和精细化奖励三大创新,让智能体第一次具备了可解释的世界建模能力。正如人类通过"观察-预测-行动"认识世界,VAGEN为AI注入的这种思考范式,或许正是通往通用人工智能的关键一步。对于开发者而言,开源的VAGEN框架不仅提供了强大的工具,更揭示了一个重要理念:让AI学会思考,比让它学会执行更重要。

专注:太空算力、AI infra、异构调度、大模型成本工程 280

算法分析与设计实验 分治策略 两路合并排序和快速排序

实验目的 理解分治法的算法思想,阅读实现书上已有的部分程序代码并完善程序, 加深对分治法 的算法原理及实现过程的理解。 实验内容 用分治法实现一组无序序列的两路合并排序和快速排序。要求清楚合并排序及快速排序 的基本原理, 编程实现分别用这两种方法将输入的一组无序序列排序为有序序列后输出。 实验代码: //分治法实现两路合并排序和快速排序 //包含所需各种头文件 #inc

Yesterday You Said Tomorrow. 6106

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

分治法-合并排序和快速排序

分治法是按照以下方案工作的: 将问题的实例划分为同一个问题的几个较小的实例,最好拥有同样的规模 对这些较小的实例求解(一般使用递归方法,但在问题规模足够小的时候,有时会利用另一种算法以提高效率) 如果必要的话,合并较小问题的解,以得到原始问题的解 分治法的流程: 4.1 合并排序 合并排序是成功应用分治技术的一个完美例子(书上说的)。 对于一个需要排序的数组,合并排序把它一分为二,并对...

weixin_33907511的博客 681

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

计算机算法分析与设计(7)---合并排序和快速排序(含C++代码)

1. 算法思想:将待排序元素集合分成大小大致相同的2个子集合(当已有数列长度是奇数时,则一半长一半短),直到分离成长度为 1 的 n 个数列(其实就是 n 个数)。将数两两合并,每次合并时进行比较和排序,直到完成排序。2. 图片讲解:先是分离成长度为 1 的 n 个数列,然后再合并,合并过程中两个红色区域代表两两比较,然后将小的放在前面。

m0_62881487的博客 625

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C语言-算法分析与设计-插入、合并、快速排序运行时间与排序元素个数的统计比较

重庆理工大学(CQUT)数组的大小在编译时就需要已知,它不能是一个运行时才能确定的变量。在你的代码中,你试图使用一个运行时确定的变量n来声明一个数组arr,这是不合法的。使用C语言进行编程时遇到了一个错误:C2131,这个错误通常表示在声明一个数组时,使用了一个非常大的数值作为其大小,而这个值并不是一个编译时常量。当n比较小时,快速排序与合并排序用时几乎相同。当n逐渐增大到3000时,快速排序比合并排序略微快一点,插入排序用时显著增加。(3)利用算法采用的设计方法,时间复杂度等分析得到该结果的原因。

西唯兵欧泡的博客 518

算法分析与设计实验一 分治策略

实验一  分治策略 实验目的:   理解分治法的算法思想,阅读实现书上已有的部分程序代码并完善程序, 加深对分治法的算法原理及实现过程的理解。 实验内容:   用分治法实现一组无序序列的两路合并排序和快速排序。要求清楚合并排序及快速排序的基本原理,编程实现分别用这两种方法将输入的一组无序序列排序为有序序列后输出。 实验代码: //分治法实现两路合并排序和快速排序 //包含所需各种头文件

Yesterday You Said Tomorrow. 2758

排序算法总结

1. 一些概念 稳定的排序:数据在经过排序后,两个相同键值的记录仍然保持原来的次序,也就是两个相同的值在排序后前后顺序不变;常见的稳定排序算法有:冒泡、插入、希尔排序 、基数排序;不稳定的排序算法有:选择排序、快速排序、堆积排序。 原地排序:指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序;希尔排序、冒泡排序、插入排序、选择排序、堆排序、快速排序都是原...

orangerfun的博客 973

【深圳大学算法设计与分析】实验一 算法性能分析(十大排序算法)

综合上述实验可得,当数据规模相当大时,选择排序、冒泡排序、插入排序耗费的时间相当多,该类算法虽然简单易懂,但是效率较低,不适合处理大量数据。合并排序和快速排序采用了分治、递归的思想,运行大量数据时效率仍然非常高,远胜于前面的几种排序算法。因此,当数据规模较大时,选择后面两种排序算法为佳。

归忆_AC的博客 2591

C++实现快速排序

它的基本思想是通过一组排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按此方法对这两部分数据进行快速排序,整个排序过程可以递归进行,以此使所有数据变成有序序列。治理:求解各个子问题。步骤二:从右向左扫描,找到小于等于 pivot 的数,如果找到,R[i] 和 R[j] 交换 ,i++。步骤三:从左向右扫描,找到大于 pivot 的数,如果找到,R[i] 和 R[j] 交换,j–。合并:按原问题的要求,将子问题的解逐层合并构成原问题的解。快速排序,是一种分治算法。

m0_50127633的博客 601

南邮算法分析与设计实验一分治法 报告

2、分析这两种排序算法在最好、最坏和平均情况下的时间复杂度。两路合并排序:最好、最坏、平均情况下的时间复杂度均为O(nlogn)。快速排序:最好、平均情况下的时间复杂度为O(nlogn),最坏情况下为O(n2。3、当初始序列是递增或递减次序排列时,通过改进主元(基准元素)的选择方法,可以提高快速排序算法运行的效率,避免最坏情况的发生。有三种主元选择方式。一是取K(left+right)/2为主元;二是取left~right之间的随机整数j,以Kj作为主元;

zyt2005815的博客 1355

2020年09月 HNUCM-OJ算法分析与设计作业6

@ZHANGQIANYI2020 HNUCM-OJ 与7相关的数,鸡兔共笼,买房,快速排序,随机化快速排序,数组合并问题 A: 与7相关的数问题 B: 鸡兔共笼问题 C: 买房问题 D: 快速排序问题 E: 随机化快速排序问题 F: 数组合并 问题 A: 与7相关的数 (时间限制: 1 Sec 内存限制: 128 MB) 题目描述: 一个正整数,如果它能被7整除,或者它的十进制表示法中某个位数上的数字为7, 则称其为与7相关的数。 现求所有小于等于n(n<100)的与7无关的正整数的平方和。

ZHANGQIANYI2020的博客 729

数据结构与算法分析 收获总结 第7章 排序

先以老师上课所讲的经典面试题: 1.把两个排好序的数组,合并为一个数组,第一个数组后半部分刚好可以容纳第一个数组的元素,空间复杂度O(1) 解析:由于空间复杂度要求,所以不可再开一个temp数组之类的方法。 void sort(int Array1[],int n,int Array2[],int m) { int p1=n-1,p2=m+n-1; int t=m-1; while(p1!=p2)...

weixin_43937162的博客 434

排序算法(待更新)

图片转自这个博主。

stm32er的博客 261
下一篇: 算法分析——Perm算法
Zephyr .
博客等级 码龄5年 29粉丝 11原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值