为什么要学习排序算法?

根据统计,早起大型机CPU资源的四分之一都花在了数据排序上面。排序算法作为最基础的算法,各种操作系统、编程语言都提供了内置的实现。既然排序实现随处可见,我们为什么还要自己动手实现呢?虽然经典算法要动手写写加深印象的道理都懂,但直到最近才发现,每种排序算法里都“暗藏玄机”。排序算法看似简单,其实不同的算法中蕴涵着经典的算法策略。通过熟练掌握排序算法,就可以掌握基本的算法设计思想,包括暴力枚举法、时间空间置换、子问题的分治以及随机化。


1.选择排序:暴力搜索

1.1 “暴力”的定义

按照Wikipedia的定义,暴力搜索也叫穷举法。它是一种常用的解决问题策略或者算法范式,通过系统化产生所有可能解来找到最终答案:

In computer science, brute-force search or exhaustive search, also known as generate and test, is a very general problem-solving technique and algorithmic paradigm that consists of systematically enumerating all possible candidates for the solution and checking whether each candidate satisfies the problem’s statement.

所谓“暴力”是指“Just do it”。需要注意的是所有解空间是来自问题定义,而非来自输入数据的所有排列组合。按照《The Design & Analysis of Algorithms》一书的定义,暴力搜索就是一种基于问题定义的、最直接的解决问题方法(“usually directly based on the problem’s statement and definitions of the concepts involved”)。

1.2 例子

比如来自Leetcode经典的2 Sum问题,问题定义里说要找到两数之和等于某值,此处暴力搜索即为穷举输入数据中所有两个数可能的组合,然后找到符合条件的一对或者多对。所以,假设输入数据规模为N(比如长度为N的数组),搜索空间只是从N个数里取出两个数的组合。类似地,线性查找最小值、查找子字符串、查找平面上最近的两个点,都可以根据问题的定义直接得到算法实现。


2.堆排序:时间空间trade-off

2.1 简介

时间和空间置换(Time and space trade-off),即用额外的空间(通常是一种高效的数据结构)来换取之后更快的处理。 其实本质上,堆排序=选择排序+堆数据结构,通过花费额外的空间,来优化“选择”这个动作。这样每次选择剩余数据中最小值的操作,其时间复杂度就从原来的线性N降低到LogN。

2.2 预处理 vs 即时维护

除了像上面堆排序,数据结构预先初始化,将解题步骤分为两阶段,也可以在执行过程中,一边执行一边维护,只要保证当前所需的数据都在结构里即可。比如,还是这个经典的2 Sum问题。如果数组未排序的话,我们可以用哈希表来记录其他元素,从而省去暴力搜索时的内层循环。哈希表可以预先初始化,也可以一边遍历数组一边维护。


3.插入排序:减而治之

所谓的减而治之(Decrease-and-Conquer),也就是增量法。要解决输入规模为N的问题,我们先解决规模为N-1的子问题,然后思考如何利用N-1的解和当前数据得到N的解。在这个过程,其实我们一直在维护一个不变量(Invariant),从而保证了所有数据处理结束后结果的正确性。根据问题规模缩减的速度,可以分为常量递减和变量递减两种方式

3.1 常量递减

常量递减(Decrease-by-a-constant-factor)即问题规模以固定的速度缩减,比如:

  • 插入排序
  • 产生排列组合:同插入排序一样
  • 二分查找:每次减半

3.2 变量递减

变量递减(Decrease-by-a-variable-factor)每次问题规模缩减的程度可变:

  • 找中位数:递减程度由选取的分区元素决定。
  • 插值查找(Interpolation search):二分查找不考虑查找值的特点,每次都折半。而插值排序根据分区的第一个、最后一个值以及要查找的值,选取一个更靠前或者靠后的值来比较。这种思想类似于在电话簿里查找一个人的电话,假如名字是A开头,则更高效的方式不是翻到中间,而是电话薄的前面。

4.归并排序:分而治之

4.1 简介

与减而治之类似,分而治之(Divide-and-Conquer)将问题一分为二,解决两个子问题后再考虑如何合并得到最终结果。

4.2 “分”和“治”

分而治之两个最重要的例子就是归并排序和快速排序。有趣的是,两者在“分”和“治”上有着完全相反的实现比重。前者重在合并,划分几乎没有额外逻辑;而后者则重在划分,合并时没有额外动作。


5.快速排序:随机化

平均情况下,快速排序的时间复杂度很不错。然后最坏情况下,它却可能恶化到与插入排序差不多的N平方。算法设计里另一种重要的思想就是利用随机化,从概率上保证最坏的情况不会发生。比如对于快速排序来说,可以随机选取,或者采样后决定要用哪个值来做划分。

为什么要学习排序算法?相关推荐

  1. 【排序算法】插入、选择、堆排、快排、归并、计数

    一.插入排序 insertSort 1.实现 2.性能分析 3.折半插入排序(了解) 二.希尔排序 ShellSort 1.原理 2.实现 3.性能分析 三.选择排序 selectSort 1.原理 ...

  2. 作为程序员,你一定要知道的十大经典排序算法!(详细解析)

    十大排序算法可以说是每个程序员都必须得掌握的了,花了一天的时间把代码实现且整理了一下,为了方便大家学习,我把它整理成一篇文章,每种算法会有简单的算法思想描述,为了方便大家理解,我还找来了动图演示:这还 ...

  3. 数据结构的六大排序算法详解

    文章目录 一.简单排序 1.Comparable接口介绍 2.冒泡排序 3.选择排序 4.插入排序 二.高级排序 1.希尔排序 2.归并排序 3.快速排序 4.排序的稳定性 一.简单排序 在我们的程序 ...

  4. 【C语言】八大排序算法

    文章目录 1.排序的概念及其应用 1.1排序的概念 1.2排序的应用 1.3常见的排序算法 1.4时间性能的测试(测试排序算法的好坏) 2.常见排序算法的实现 2.1直接插入排序 2.2希尔排序 2. ...

  5. 【js排序算法】--基础排序算法

    前言 前端的代码运行环境本来就不善于处理大量的数据计算,前端也有很多东西比算法重要.那我们为什么要学习算法? 明确学习和使用算法的目的. 一个排序功能,用冒泡排序法,归并排序法,快速排序法?who t ...

  6. 《数据结构与算法》(二十五)- 排序算法:快速排序

    目录 前言 1. 快速排序 1.1 快速排序算法 1.2 快速排序算法复杂度分析 1.3 快速排序优化 2. 总结 原文地址:https://program-park.github.io/2021/1 ...

  7. 基于使用学习排序算法的Web服务学习的个性化的决策战略

    摘要----为了从类似的服务列表中进行功能上的选择,用户往往需要根据多个QoS准则做出他们的决定,它们需要对目标服务.在这个过程中,不同的用户可能遵循不同的决策策略,有些是补偿性的,在这个补偿中在所有 ...

  8. 伍六七带你学算法 进阶篇-排序算法

    给定一个整数数组 nums,将该数组升序排列. 示例 1: 输入:[5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:[5,1,1,2,0,0] 输出:[0,0,1,1,2,5] 各排序算 ...

  9. C++排序算法实现(更新中)

    比较排序法:如冒泡排序.简单选择排序.合并排序.快速排序.其最优的时间复杂度为O(nlogn). 其他排序法:如桶排序.基数排序等.时间复杂度可以达到O(n).但试用范围有要求. 桶排序:排序的数组元 ...

最新文章

  1. C# 图片旋转360度程序
  2. gstreamer开发日志
  3. ubuntu禁用锁屏
  4. OpenCV 离散傅里叶变换
  5. Java虚拟机最多支持多少个线程?
  6. Java API简介以及以及常用的类库介绍
  7. paip.中文 分词 -- 同义词大全整理
  8. python从入门到精通 清华大学出版社-清华大学出版社 python
  9. arm开发板挂载win10和ubuntu haneWIN NFS Server
  10. JavaScript网页cookie的“简单”设置
  11. 07 Halcon 点云平面角测量
  12. matlab 交互界面设计
  13. 软件测试女生可以学习么?现在还能入行么?
  14. Kotlin by lazy解析及在findviewById场景中的使用
  15. 3种方式构造HTTP请求详解(HTTP4)
  16. creator 反复横跳瞄准线的实现
  17. 关于滑动时对背景动态高斯模糊的自定义控件
  18. 2013-2014-1(实变函数56, 常微分方程64)
  19. mysql整数转为2位小数_SQL整数转换成小数
  20. LTE入门, 从这本书开始

热门文章

  1. Python入门习题大全——检查用户名
  2. mk突变点检测_mk突变检测
  3. Web前端,CSS中的浮动、清除浮动
  4. 在Github账户如何修改设置个人头像
  5. 数据库 SQL Server 检测到基于一致性的逻辑 I/O 错误 页撕裂 执行 读取 期间,发生了该错误 恢复
  6. Falsehoods Programmers Believe About Names
  7. c语言uint64_t转String,C语言编程 8字节的数据转换为uint64_t类型数据
  8. python图案填充_用matplotlib用自定义图案填充多边形
  9. 20110621 晴
  10. 前端低代码平台腾讯云微搭使用文档