首页 > 编程语言 >排序算法之总述

排序算法之总述

时间:2024-08-12 19:54:45浏览次数:15  
标签:总述 log 复杂度 算法 数组 n2 排序


title: 排序算法
date: 2024-7-18 15:20:07 +0800
categories:

  • 汇总
    tags:
  • 排序
  • 算法
  • 时间复杂度
  • 汇总
    description: 排序算法(sorting algorithm)用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用,因为有序数据通常能够被更高效地查找、分析和处理。
    math: true

排序算法(sorting algorithm)用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用,因为有序数据通常能够被更高效地查找、分析和处理。

排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定,如数字大小、字符 ASCII 码顺序或自定义规则。

评价维度

运行效率:我们期望排序算法的时间复杂度尽量低,且总体操作数量较少(时间复杂度中的常数项变小)。对于大数据量的情况,运行效率显得尤为重要。

  • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

就地性:顾名思义,原地排序通过在原数组上直接操作实现排序,无须借助额外的辅助数组,从而节省内存。通常情况下,原地排序的数据搬运操作较少,运行速度也更快。

  • 空间复杂度: 是指算法在计算机

稳定性稳定排序在完成排序后,相等元素在数组中的相对顺序不发生改变。

  • 稳定性:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

自适应性自适应排序的时间复杂度会受输入数据的影响,即最佳时间复杂度、最差时间复杂度、平均时间复杂度并不完全相等。

自适应性需要根据具体情况来评估。如果最差时间复杂度差于平均时间复杂度,说明排序算法在某些数据下性能可能劣化,因此被视为负面属性;而 如果最佳时间复杂度优于平均时间复杂度,则被视为正面属性。

是否基于比较基于比较的排序依赖比较运算符( < < <、 = = =、 > > >)来判断元素的相对顺序,从而排序整个数组,理论最优时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn) 。而非比较排序不使用比较运算符,时间复杂度可达 O ( n ) O(n) O(n) ,但其通用性相对较差。

理想的排序算法

运行快、原地、稳定、正向自适应、通用性好。显然,迄今为止尚未发现兼具以上所有特性的排序算法。因此,在选择排序算法时,需要根据具体的数据特点和问题需求来决定。

总述

冒泡排序

冒泡排序通过交换相邻元素来实现排序。通过添加一个标志位来实现提前返回,我们可以将冒泡排序的最佳时间复杂度优化到 O ( n ) O(n) O(n) 。

插入排序

插入排序每轮将未排序区间内的元素插入到已排序区间的正确位置,从而完成排序。虽然插入排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2) ,但由于单元操作相对较少,因此在小数据量的排序任务中非常受欢迎。

快速排序

快速排序基于哨兵划分操作实现排序。在哨兵划分中,有可能每次都选取到最差的基准数,导致时间复杂度劣化至 O ( n 2 ) O(n^2) O(n2) 。引入中位数基准数或随机基准数可以降低这种劣化的概率。尾递归方法可以有效地减少递归深度,将空间复杂度优化到 O ( log ⁡ n ) O(\log n) O(logn) 。

归并排序

归并排序包括划分和合并两个阶段,典型地体现了分治策略。在归并排序中,排序数组需要创建辅助数组,空间复杂度为 O ( n ) O(n) O(n) ;然而排序链表的空间复杂度可以优化至 O ( 1 ) O(1) O(1) 。

桶排序

桶排序包含三个步骤:数据分桶、桶内排序和合并结果。它同样体现了分治策略,适用于数据体量很大的情况。桶排序的关键在于对数据进行平均分配。

计数排序

计数排序是桶排序的一个特例,它通过统计数据出现的次数来实现排序。计数排序适用于数据量大但数据范围有限的情况,并且要求数据能够转换为正整数。

基数排序

基数排序通过逐位排序来实现数据排序,要求数据能够表示为固定位数的数字。

  • 总的来说,我们希望找到一种排序算法,具有高效率稳定原地以及正向自适应性等优点。然而,正如其他数据结构和算法一样,没有一种排序算法能够同时满足所有这些条件。在实际应用中,我们需要根据数据的特性来选择合适的排序算法。

常见排序算法及其时间复杂度的比较表:

  • n: 待排序元素的数量
  • k: 桶排序和计数排序中的数值范围或基数排序中的数字基数
排序算法时间复杂度空间复杂度稳定性
最佳平均最差
冒泡排序 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
插入排序 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
折半插入排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
归并排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n ) O(n) O(n)稳定
快速排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( log ⁡ n ) O(\log n) O(logn)不稳定
堆排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( 1 ) O(1) O(1)不稳定
希尔排序 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)取决于间隔序列 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
基数排序 O ( n k ) O(nk) O(nk) O ( n k ) O(nk) O(nk) O ( n k ) O(nk) O(nk) O ( n + k ) O(n + k) O(n+k)稳定
计数排序 O ( n + k ) O(n + k) O(n+k) O ( n + k ) O(n + k) O(n+k) O ( n + k ) O(n + k) O(n+k) O ( n + k ) O(n+k) O(n+k)稳定
桶排序 O ( n ) O(n) O(n) O ( n + k ) O(n + k) O(n+k) O ( n 2 ) O(n^2) O(n2) O ( n ⋅ k ) O(n \cdot k) O(n⋅k)稳定
鸡尾酒排序 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
梳排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) Ω ( n 2 2 p ) \Omega (\frac{n^2}{2^p}) Ω(2pn2​) Ω ( n 2 ) \Omega(n^2) Ω(n2) O ( 1 ) O(1) O(1)不稳定
奇葩排序算法
睡眠排序 O ( n ) O(n) O(n)不确定不确定 O ( 1 ) O(1) O(1)不稳定
随机排序 O ( n ) O(n) O(n)不确定不确定 O ( 1 ) O(1) O(1)不稳定

Q & A

Q:排序算法稳定性在什么情况下是必需的?

在现实中,我们有可能基于对象的某个属性进行排序。例如,学生有姓名和身高两个属性,我们希望实现一个多级排序:先按照姓名进行排序,得到 (A, 180) (B, 185) (C, 170) (D, 170) ;再对身高进行排序。由于排序算法不稳定,因此可能得到 (D, 170) (C, 170) (A, 180) (B, 185)

可以发现,学生 D 和 C 的位置发生了交换,姓名的有序性被破坏了,而这是我们不希望看到的。

Q:哨兵划分中“从右往左查找”与“从左往右查找”的顺序可以交换吗?

不行,当我们以最左端元素为基准数时,必须先“从右往左查找”再“从左往右查找”。这个结论有些反直觉,我们来剖析一下原因。

哨兵划分 partition() 的最后一步是交换 nums[left]nums[i] 。完成交换后,基准数左边的元素都 <= 基准数,这就要求最后一步交换前 nums[left] >= nums[i] 必须成立。假设我们先“从左往右查找”,那么如果找不到比基准数更大的元素,则会在 i == j 时跳出循环,此时可能 nums[j] == nums[i] > nums[left]。也就是说,此时最后一步交换操作会把一个比基准数更大的元素交换至数组最左端,导致哨兵划分失败。

举个例子,给定数组 [0, 0, 0, 0, 1] ,如果先“从左向右查找”,哨兵划分后数组为 [1, 0, 0, 0, 0] ,这个结果是不正确的。

深入思考一下,如果我们选择 nums[right] 为基准数,那么正好反过来,必须先“从左往右查找”。

Q:关于尾递归优化,为什么选短的数组能保证递归深度不超过 log ⁡ n \log n logn ?

递归深度就是当前未返回的递归方法的数量。每轮哨兵划分我们将原数组划分为两个子数组。在尾递归优化后,向下递归的子数组长度最大为原数组长度的一半。假设最差情况,一直为一半长度,那么最终的递归深度就是 log ⁡ n \log n logn 。

回顾原始的快速排序,我们有可能会连续地递归长度较大的数组,最差情况下为 n n n、 n − 1 n - 1 n−1、 … \dots …、 2 2 2、 1 1 1 ,递归深度为 n n n 。尾递归优化可以避免这种情况出现。

Q:当数组中所有元素都相等时,快速排序的时间复杂度是 O ( n 2 ) O(n^2) O(n2) 吗?该如何处理这种退化情况?

是的。对于这种情况,可以考虑通过哨兵划分将数组划分为三个部分:小于、等于、大于基准数。仅向下递归小于和大于的两部分。在该方法下,输入元素全部相等的数组,仅一轮哨兵划分即可完成排序。

Q:桶排序的最差时间复杂度为什么是 O ( n 2 ) O(n^2) O(n2) ?

最差情况下,所有元素被分至同一个桶中。如果我们采用一个 O ( n 2 ) O(n^2) O(n2) 算法来排序这些元素,则时间复杂度为 O ( n 2 ) O(n^2) O(n2) 。

标签:总述,log,复杂度,算法,数组,n2,排序
From: https://blog.csdn.net/rd_w_csdn/article/details/141140272

相关文章

  • 排序算法之桶排序
    title:桶排序date:2024-7-2518:58:19+0800categories:排序算法tags:排序算法桶排序description:桶排序(bucketsort)是分治策略的一个典型应用。它通过设置一些具有大小顺序的桶,每个桶对应一个数据范围,将数据平均分配到各个桶中;然后,在每个桶内部分别执行排序;最终按......
  • 排序算法之归并排序
    title:归并排序date:2024-7-1915:03:06+0800categories:排序算法tags:排序算法归并排序description:归并排序(MergeSort)是一种基于分治法的有效排序算法。它将一个列表分成较小的子列表,对每个子列表进行排序,然后合并这些子列表以产生一个有序列表。math:true......
  • NDT算法详解与C++实现
    点云匹配在感知环节是一个很重要的信息获取手段,而其中的算法也有几个比较经典了,例如ICP(IterativeClosestPoint,迭代最近点)算法,而本文决定记录学习的是NDT算法,也就是NormalDistributionTransform,正态分布变换算法。什么是正态分布变换算法呢,简言之,就是把空间中的点云进行整......
  • 怎样在 SQL 中对一个包含销售数据的表按照销售额进行降序排序?
    在当今数字化商业的浪潮中,数据就是企业的宝贵资产。对于销售数据的有效管理和分析,能够为企业的决策提供关键的支持。而在SQL中,对销售数据按照销售额进行降序排序,是一项基础但极其重要的操作。想象一下,您面前有一张庞大的销售数据表,其中记录了各种产品在不同时间、不同地......
  • 2024华为OD笔试机试 - 模拟目录管理功能 (python/c++/java D卷C卷真题算法)
    华为OD机试(C卷+D卷)2024真题目录(Java&c++&python)题目描述实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。支持命令:创建目录命令:mkdir目录名称,如mkdirabc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作。此命令无输出......
  • 6-61 顺序表基本运算算法的实现
    线性表实验一实现顺序表各种基本运算的算法目的:领会顺序表存储结构和掌握顺序表中各种基本运算算法设计。内容:编写程序,实现顺序表的各种基本运算算法(假设顺序表的元素类型ElemType为char),并在此基础上设计一个主程序,完成如下功能:(1)初始化顺序表L。(2)依次插入a、b......
  • 「代码随想录算法训练营」第三十五天 | 动态规划 part8
    121.买卖股票的最佳时机题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/文章讲解:https://programmercarl.com/0121.买卖股票的最佳时机.html题目难度:简单视频讲解:https://www.bilibili.com/video/BV1Xe4y1u77q题目状态:有一半的思路思路一:贪心对......
  • 足球比赛结果预测系统:遗传算法的研究
    引言最近有个朋友时运不济,自己胡乱玩被足球预测的推子骗了一回又一回,明明我就是专门做足球预测的,偏偏不信我还赌气说自己有本事一个人也能成,现在隔得跟个小怨妇似得,觍着脸回来找我要我传他心得,没办法,好歹十几年的兄弟,他再怎么发病也只能原谅他了,于是就有了这篇文章。不过足球......
  • 【算法学习】排序算法汇总
    冒泡排序1、冒泡排序简介冒泡排序的英文BubbleSort,是一种最基础的交换排序。之所以叫做冒泡排序,因为每一个元素都可以像小气泡一样,根据自身大小一点一点向数组的一侧移动冒泡排序的原理:冒泡轮数:每一轮只能将该轮中最大的数排至最后面。即第一轮只能确定将末位上的数归位......
  • 【算法学习】算法时间复杂度
    时间复杂度的计算时间复杂度简单计算(一层、两层、多层循环)相当于轨迹追踪法:设执行次数为k,按照循环条件阿布算法课学习链接01区别算法(Algorithm)和程序(Program)算法程序设计阶段实施阶段相关领域知识程序员任何语言、伪代码编程语言独立于硬件......