数据结构与算法之美学习笔记:14 | 排序优化:如何实现一个通用的、高性能的排序函数?

news2024/11/29 14:53:05

目录

  • 前言
  • 如何选择合适的排序算法?
  • 如何优化快速排序?
  • 举例分析排序函数

前言

在这里插入图片描述
本节课程思维导图:
在这里插入图片描述
几乎所有的编程语言都会提供排序函数,比如 C 语言中 qsort(),C++ STL 中的 sort()、stable_sort(),还有 Java 语言中的 Collections.sort()。那你知道这些排序函数是如何实现的吗?底层都利用了哪种排序算法呢?
抛出问题:如何实现一个通用的、高性能的排序函数?

如何选择合适的排序算法?

我们先回顾一下前面讲过的几种排序算法。
在这里插入图片描述
我们前面讲过,线性排序算法的时间复杂度比较低,适用场景比较特殊。所以如果要写一个通用的排序函数,不能选择线性排序算法。
如果对小规模数据进行排序,可以选择时间复杂度是 O(n2) 的算法;如果对大规模数据进行排序,时间复杂度是 O(nlogn) 的算法更加高效。所以,为了兼顾任意规模数据的排序,一般都会首选时间复杂度是 O(nlogn) 的排序算法来实现排序函数。

时间复杂度是 O(nlogn) 的排序算法不止一个,我们已经讲过的有归并排序、快速排序,后面讲堆的时候我们还会讲到堆排序。堆排序和快速排序都有比较多的应用,比如 Java 语言采用堆排序实现排序函数,C 语言使用快速排序实现排序函数。归并排序的情况其实并不多,因为归并排序并不是原地排序算法,空间复杂度是 O(n)。
前面我们讲到,快速排序比较适合来实现排序函数,但是,我们也知道,快速排序在最坏情况下的时间复杂度是 O(n2),如何来解决这个“复杂度恶化”的问题呢?

如何优化快速排序?

如果数据原来就是有序的或者接近有序的,每次分区点都选择最后一个数据,那快速排序算法就会变得非常糟糕,时间复杂度就会退化为 O(n2)。实际上,这种 O(n2) 时间复杂度出现的主要原因还是因为我们分区点选得不够合理。
最理想的分区点是:被分区点分开的两个分区中,数据的数量差不多。
我这里介绍两个比较常用、比较简单的分区算法。

  1. 三数取中法
    我们从区间的首、尾、中间,分别取出一个数,然后对比大小,取这 3 个数的中间值作为分区点。这样每间隔某个固定的长度,取数据出来比较,将中间值作为分区点的分区算法,肯定要比单纯取某一个数据更好。但是,如果要排序的数组比较大,那“三数取中”可能就不够了,可能要“五数取中”或者“十数取中”。
  2. 随机法
    随机法就是每次从要排序的区间中,随机选择一个元素作为分区点。这种方法并不能保证每次分区点都选的比较好,但是从概率的角度来看,也不大可能会出现每次分区点都选得很差的情况,所以平均情况下,这样选的分区点是比较好的。时间复杂度退化为最糟糕的 O(n2) 的情况,出现的可能性不大。

快速排序是用递归来实现的。递归要警惕堆栈溢出。为了避免快速排序里,递归过深而堆栈过小,导致堆栈溢出,我们有两种解决办法:第一种是限制递归深度。一旦递归过深,超过了我们事先设定的阈值,就停止递归。第二种是通过在堆上模拟实现一个函数调用栈,手动模拟递归压栈、出栈的过程,这样就没有了系统栈大小的限制。

举例分析排序函数

我拿 Glibc 中的 qsort() 函数举例说明一下。

对于小数据量时,qsort() 会优先使用归并排序来排序输入数据;要排序的数据量比较大的时候,qsort() 会改为用快速排序算法来排序;
qsort() 选择分区点的方法就是“三数取中法”。递归太深会导致堆栈溢出的问题,qsort() 是通过自己实现一个堆上的栈,手动模拟递归来解决的。实际上,qsort() 并不仅仅用到了归并排序和快速排序,它还用到了插入排序。在快速排序的过程中,当要排序的区间中,元素的个数小于等于 4 时,qsort() 就退化为插入排序。

在小规模数据面前,O(n2) 时间复杂度的算法并不一定比 O(nlogn) 的算法执行时间长。我们在讲复杂度分析的时候讲过,算法的性能可以通过时间复杂度来分析,但是,这种复杂度分析是比较偏理论的,如果我们深究的话,实际上时间复杂度并不等于代码实际的运行时间。时间复杂度代表的是一个增长趋势,如果画成增长曲线图,你会发现 O(n2) 比 O(nlogn) 要陡峭,也就是说增长趋势要更猛一些。但是,我们前面讲过,在大 O 复杂度表示法中,我们会省略低阶、系数和常数,也就是说,O(nlogn) 在没有省略低阶、系数、常数之前可能是 O(knlogn + c),而且 k 和 c 有可能还是一个比较大的数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1166100.html

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

相关文章

游戏中的-雪花算法

1、什么是雪花算法? 雪花算法(Snowflake)是一种生成唯一ID的算法。在游戏开发过程中会为玩家生成唯一的id,或者玩家获得一件装备,为这件装备生成唯一的Id,将此角色和装备的Id保存于数据库当中。 全局唯一性…

Spring-AOP-面向切面编程

文章目录 目录 文章目录 前言 一 . 场景设定和问题复现 二 . 解决技术[代理模式] 2.1 代理模式 2.2 静态代理 2.3 动态代理 三 . 面向切面编程思想(AOP) 3.1 面向切面编程思想 3.2 AOP 思想的应用场景 3.3 AOP术语名词介绍 3.3.1 横切关注点 3.3.2 通知(增强) 3…

面试算法52:展平二叉搜索树

题目 给定一棵二叉搜索树,请调整节点的指针使每个节点都没有左子节点。调整之后的树看起来像一个链表,但仍然是二叉搜索树。 分析 看起来需要按照节点的值递增的顺序遍历二叉搜索树中的每个节点,并将节点用指向右子节点的指针连接起来。这…

观测云产品更新 | 单点登录新增 OIDC / Oauth2.0 协议、数据转发优化、场景优化等

观测云更新 数据转发 1. 新增【观测云】选项,支持将数据保存到观测云的对象存储,计费逻辑按天出账,每天统计存储的压缩后的数据大小,按照每 GB 0.007 元出具对应账单。 2. 数据转发菜单导航位置调整至【管理】模块,…

ActiveMQ是什么?-九五小庞

MQ是消息中间件,是一种在分布式系统中应用程序借以传递消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的开源项目,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现。特点:1、支持多种语言…

黑色星期五来袭,Ozon为你提供丰富的推广工具和资源,助你实现销售突破!

Ozon的“黑色星期五”促销活动为卖家们提供了丰富的推广工具和资源,以确保他们的商品在促销期间获得最大的曝光度和销售额。卖家们应该充分利用这些机会,制定合适的折扣策略,并确保他们的商品在Ozon平台上脱颖而出。 为了推广Ozon黑色星期五促…

AI、万圣节与聊斋;用AI写甜蜜恋爱小暖文;AGI新趋势与机会洞察;Meta官方Llama 2入门指南 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 👀 时代杂志评选2023年度最佳发明,AI赛道入选名单 https://time.com/collection/best-inventions-2023 10 月 24 日&#xff…

java那些数据类型是安全加锁的。

我还没有反应过来,首先考虑的是基本数据类型,因为底层这块儿是在没有看过,Spring是被final修饰不可变的。后来才明白,原来是问你线程安全问题。 锁数据类型。 其实就是被synchronized修饰过的数据类型。 例如StringBuffer 底层 …

国外住宅IP代理测评选择的8个方法,稳定的海外IP哪个靠谱?

一、国外住宅IP代理是什么? 代理服务器充当您和互联网之间的网关。它是一个中间服务器,将最终用户与他们浏览的网站分开。如果您使用国外代理IP,互联网流量将通过国外代理服务器流向您请求的地址。然后,请求通过同一个代理服务器…

C++类和对象下(初始化列表,静态成员,explicit关键字,友元)

C类和对象下[初始化列表,静态成员,explicit关键字,友元] 一.初始化列表1.为什么会有初始化列表2.初始化列表的语法形式3.没有默认构造函数的自定义成员变量4.初始化列表是成员变量定义的地方5.初始化列表可以跟函数体内定义搭配使用6.初始化列表执行的顺序7.总结建议 二.静态成…

KT6368A蓝牙芯片发送指令设置中文蓝牙名是乱码 这个要如何处理

目录 一、KT6368A蓝牙芯片为什么发送at指令设置中文spp蓝牙名,是乱码 这个要如何处理 第一步,在pc端新建一个txt文档,将您需要的名字,汉字打出来,另存为UTF-8编码 第二步,使用winhex软件,当然…

JVS智能BI(自助式商业分析)本周更新内容已上线

在数据分析与可视化的世界中,我们始终在寻找新的创新与突破,以帮助用户更高效、更直观地理解数据,洞察业务的深层逻辑。本周更新包含了一系列的新功能、优化及bug修复,更新如下: 新增: 1.新增图表分类功能&#xff1…

宝宝洗衣机哪个牌子质量好?小型洗衣机质量排名

说起洗衣服,大部分的家庭都会备有一台洗衣机,不过如果有婴儿的话,贴心的宝妈宝爸也会特意将宝宝的衣服与大人的衣服分开来进行清洗。很多妈妈都会自己动手洗。由于婴儿的皮肤比较娇嫩、敏感,所以儿童的衣物与成人的衣物混合使用&a…

视频特效制作软件:After Effects 2024 mac中文版新增功能

After Effects 2024 mac是一款专业的视频特效和动态图形设计软件,它可以帮助用户创建各种令人惊叹的视觉效果,例如粒子系统、合成特效、绿屏抠像等。该软件支持动画制作,包括关键帧动画、形状动画、运动跟踪等工具,可以创建复杂的…

数据库实验报告(五)

1、实验目的 (1) 掌握对聚集函数的使用 (2) 掌握对分组的使用 (3) 掌握非关联子查询的用法,了解相关的连接谓词 2、实验预习与准备 (1) 了解Max&#x…

面试算法53:二叉搜索树的下一个节点

题目 给定一棵二叉搜索树和它的一个节点p,请找出按中序遍历的顺序该节点p的下一个节点。假设二叉搜索树中节点的值都是唯一的。例如,在图8.9的二叉搜索树中,节点8的下一个节点是节点9,节点11的下一个节点是null。 分析&#xf…

Web开发介绍详细介绍

Web开发介绍 1 什么是web开发 Web:全球广域网,也称为万维网(www World Wide Web),能够通过浏览器访问的网站。 所以Web开发说白了,就是开发网站的,例如下图所示的网站:淘宝,京东等等 那么我们…

常见接口测试面试题

1、按你的理解,软件接口是什么? 答: 就是指程序中具体负责在不同模块之间传输或接受数据的并做处理的类或者函数。 2、HTTP和HTTPS协议区别? 答: https协议需要到CA(Certificate Authority,证书…

犀牛8 for Mac – 强大的三维建模软件,轻松实现创意设计

你是否正在寻找一款功能强大、易于使用的三维建模软件?犀牛8 for Mac是你的不二选择!作为最新版本的犀牛系列软件,它汇集了众多令人惊叹的特性,让你能够轻松实现自己的创意设计。 犀牛8 for Mac拥有丰富而强大的三维建模工具&…

【Python基础】变量基本使用

变量 1.变量定义02. 变量的类型2.1 变量类型的演练 —— 个人信息2.2 变量的类型2.3转义字符 3.变量输入输出3.1变量格式化输出 4.变量命名 1.变量定义 变量定义 • 在 Python 中,每个变量 在使用前都必须赋值 在使用前都必须赋值,变量 赋值以后 该变量…