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

程序员面试必备——动画详解十大经典排序算法(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,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少, 阅读详情

相关推荐

基于TL431与光耦的电压反馈环路优化设计实战

本文深入探讨了基于TL431与光耦的电压反馈环路优化设计实战。文章从理解这对“黄金搭档”的工作原理入手,详细拆解了电压采样电阻网络、偏置电路、光耦工作点设置以及动态补偿网络的设计心法与计算步骤。重点分享了如何通过RC补偿网络调试,确保环路在各种负载下稳定可靠,并提供了关键的实战避坑指南,帮助工程师解决电源设计中常见的振荡、噪声及可靠性问题。

nginx7reverse的博客 777

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

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

实践求真知 6161

实用电路精讲系列---双级运放放大电路(差分放大+跟随缓冲)

本文分析了双极运放放大电路的工作原理及其典型应用。该电路结合差分放大器和跟随缓冲器,实现高精度信号放大与阻抗匹配。差分放大器通过放大差模信号并抑制共模噪声提升信噪比;跟随缓冲器则提供阻抗变换,确保信号稳定传输。两者协同工作可优化输入阻抗、增强噪声抑制并提高设计灵活性。文章还列举了10个典型应用案例,包括医疗设备、工业传感器和新能源系统等,展示了该电路在精密电子系统中的关键作用。最后通过实用电路分析,详细说明了各模块功能及设计注意事项。

weixin_40590799的博客 2954

分治法实现合并排序

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

海棠的博客 2844

ubuntu18.04美化主题(完整版)

和网上的美化一样,但是我当初跟着博客美化的时候遇到一些问题,按博客的做法无法解决。 所以我自己也写一篇关于ubuntu18.04美化主题的博客。 第一步:安装主题工具:GNOME Tweaks sudo apt-get update sudo apt-get install gnome-tweak-tool 然后安装完成后我们打开Tweaks(截图如下): 第二步,修改窗口按钮位...

B丶atty的博客 7万+

通达信-申万宏源金融终端本地数据转sqlite3,2、解析申万宏源C:/zd_swhy_gm/vipdoc/sh/lday的sh600000股票数据

为量化做准备,通达信-申万宏源金融终端本地数据转sqlite3,解析申万宏源C:/zd_swhy_gm/vipdoc/sh/lday的sh600000股票数据

wuyaqi的博客 510

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

合并排序(归并排序) 合并排序是成功应用分治技术的一个完美例子。对于一个需要排序的数组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

在UI界面中播放视频_unity基础开发教程

之前我写过一篇在场景中播放视频的文章,但是在开发中有时候也会在UI的界面中播放视频,这期我们做一下在UI的界面中播放视频。操作步骤比较简单,到这里就完成了,如果有问题的话可以在评论区留言,下期见,拜拜!

为者常成,行者常至! 2010

合并排序(归并排序 MergeSort)

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

指尖飞舞 1008

【100%通过率】华为od机试C卷【出差 / 员工派遣】Java&Go 实现

某公司部门需要派遣员工去国外做项目。现在,代号为 x 的国家和代号为 y 的国家分别需要 cntx 名和 cnty 名员工部门每个员工有一个员工号 (1,2,3,......),工号连续,从 1开始。部长派遣员工的规则:

MISAYAONE的博客 2639

Codex 桌面端自定义模型列表为空 — 修复记录

摘要:Codex桌面端首次启动正常,但二次启动后出现中文界面且模型列表丢失。问题根源在于Electron的Chromium持久化状态损坏,导致UI渲染异常。解决方案包括:1) 将config.toml中的模型路径改为绝对路径;2) 删除损坏的状态文件.codex-global-state.json;3) 清除Chromium用户数据目录AppData\Roaming\Codex\web。验证显示修改后模型功能恢复正常,重装无效的原因是卸载未清除用户数据目录。

猿小白的博客 1153

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

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

x24_my的博客 373

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

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

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

Yesterday You Said Tomorrow. 6106

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

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

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

weixin_33907511的博客 681

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

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

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

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

m0_62881487的博客 625

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、付费专栏及课程。

余额充值