排序整理2

一、一些概念

  1. 排序方法是“稳定的”:假设两个元素相等,若在排序后的序列中,排序前就在前面的元素仍在前面,则称所用的排序方法是稳定的;反之,若排序后两个相等元素调换相对位置,则称所用的排序方法是不稳定的

二、分类

  1. 按排序过程中的原则:
    • 插入排序
    • 交换排序
    • 选择排序
    • 归并排序
    • 计数排序
  2. 按内部排序过程中所需的工作量:
    • 简单的排序算法:时间复杂度为 O ( n 2 ) O(n^2) O(n2)
    • 先进的排序算法:时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
    • 基数排序:时间复杂度为 O ( d ⋅ n ) O(d\cdot n) O(dn)

三、一些准备工作

待排记录的数据类型设为:

#define MAXSIZE 20 // 一个用作示例的小顺序表的最大长度
typedef int KeyType;  // 定义关键字类型为整数类型
typedef struct {KeyType key;  // 关键字项InfoType otherinfo;  // 其他数据项
} RedType;  // 记录类型typedef struct {RedType r[MAXSIZE+1];  // r[0]闲置或用作哨兵单元int length;  // 顺序表长度
} SqList;  // 顺序表类型

四、插入排序

每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中

  1. 直接插入排序:将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表
    • 一趟直接插入排序:一趟会将一个记录插入有序表,有序表的记录数+1.
    • 整个排序过程为n-1趟插入
    • 算法分析
      void InsertSort(SqList &L){for (int i=2; i<L.length; ++i)if (L.r[i].key<L.r[i-1].key){L.r[0] = L.r[i];L.r[i] = L.r[i-1];for (j=i-2; L.r[0].key<L.r[j].key; --j)L.r[j+1] = L.r[j];  // 记录后移L.r[j+1] = L.r[0];  // 将当前元素插入到正确位置}
      }
      
  2. 折半插入排序:由于插入排序的基本操作是在一个有序表中进行查找和插入,因此这个“查找”操作可利用“折半查找”来实现
void BInsertSort(SqList &L){for (i=2; i<L.length; ++i){L.r[0] = L.r[i];low = 1; high = i - 1;while (low<=high){m = (low+high) / 2;if (L.r[0].key<L.r[m].key)  high = m-1;  // 插入点在低半区else low = m+1;  // 插入点在高半区}for (j=i-1; j>=high+1; --j)  L.r[j+1] = L.r[j];  // 记录后移L.r[high+1] = L.r[0];  // 插入}
}
  1. 希尔排序:又称缩小增量排序,也是一种插入排序类的算法,但时间效率较上述有较大改进
    • 思想:对于直接插入排序,若待排序列原本就为正序,其时间复杂度可提高为 O ( n ) O(n) O(n),由此可知若待排序序列关键字基本有序,则直接插入排序的效率可大大提高
    • 原理:先将整个待排序列分割成若干子序列,分别进行直接插入排序,由此可让整个序列中的记录“基本有序”,此时再对全体记录进行一次直接插入排序。这样一来,前后记录位置的增量是dk而不是1

五、交换排序

根据序列中两个关键字的比较结果来对换这两个记录在序列中的位置

  1. 起泡排序:
    • 一趟排序:先比较第一个和第二个,若为逆序则交换;再比较第二个和第三个,以此类推,直至第n-1个和第n个记录的关键字对比完为止。这称为第一趟起泡排序
    • 第i趟排序会使关键字第i大的记录被安置到正确的位置上
    • 判别起泡排序结束的条件:在一趟排序过程中没有进行过交换记录的操作
  2. 快速排序:通过一趟排序将待排序列分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后分别对这两部分继续进行排序,以达到整个序列有序
    • 一趟排序:任意选一个记录作为枢轴pivotkey,将所有小于它的记录都放在它之前,所有大于它的都放在它之后。具体做法是:附设两个指针low和high,首先从high所指位置起向前搜索找到第一个小于pivotkey的记录放到low位置上,然后从low下一个位置起向后搜索找到第一个大于pivotkey的记录放到high位置上。重复这两步直到low=high为止
    • 一趟排序结束会将枢轴放到正确位置上(即最后high=low的位置处)
    • 当初始序列有序/逆序或基本有序/逆序时,快速排序会退化为起泡排序

六、选择排序

每一趟在待排序元素中,选取关键字最小(或最大)的元素加入有序子序列

  1. 简单选择排序:
    • 第i趟排序:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录交换
    • 简单选择排序中,所需进行记录移动的次数比较少(因为只是比较+给min的下标赋值),而无论记录的初始排列如何,所需进行的关键字间的比较次数相同
  2. 堆排序:
    • 堆的定义:n个元素的序列 k 1 , k 2 , . . . , k n {k_1, k_2, ..., k_n} k1,k2,...,kn当且仅当满足下关系时,称之为堆:
      请添加图片描述
    • 堆排序要解决两个问题:1)如何由一个无序序列建成一个堆;2)如何在输出堆顶元素后,调整剩余元素成为一个新的堆
      • 2)堆顶元素和堆底元素互换(即输出堆顶元素,然后以堆底元素替换之),然后自上而下进行调整即可,称这个“自堆顶至叶子”的调整过程为“筛选”
      • 1)从一个无序序列建堆的过程就是一个反复“筛选”的过程。且只需要从第 ⌊ n 2 ⌋ \lfloor \frac{n}{2} \rfloor 2n 个元素开始,依次往前筛选即可
    • 堆排序方法对于记录数较少的文件并不提倡,而对于n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整新堆时进行的反复“筛选”上(即代码中的HeadAdjust)。对深度为k的堆,筛选算法中进行的关键字比较次数至多为2(k-1)次
    • 堆排序在最坏的情况下,其时间复杂度也为 O ( n l o g n ) O(nlogn) O(nlogn),且仅需一个记录大小供交换用的辅助存储空间

外部排序

  1. 外部排序基本上由两个相对独立的阶段组成:
    • (初始)归并段:按照可用内存大小,将外存上含n个记录的文件分成若干长度为l的子文件或段,依次读入内存并利用有效的内部排序方法对每个子文件各自进行排序,并将排序后得到的有序子文件重新写入外存,通常称这些有序子文件为归并段或顺串(这一阶段是内部排序的内容,就是逐个段读入内存,然后直接内部排序,最后再写回外存。若用于内部排序的内存工作区能容纳 l l l个记录,则初始归并段中就包含 l l l个记录,如下图)
      请添加图片描述
    • 然后对这些归并段进行逐趟归并,使归并段(有序的子文件)逐渐由小至大,直至得到整个有序文件为止(这一阶段是外部排序主要探讨的问题,也就是归并的过程)
  2. 一个2-路平衡归并的具体例子:假设有一个含10000个记录的文件
    • 首先通过10次内部排序得到10个初始归并段,每一段都含有1000个记录
    • 然后对这些初始归并段两两作归并
    • 然后对第一次归并得到的5个归并段再两两归并
    • 然后对第二次归并得到的3个归并段再两两归并
    • 然后对第四次归并得到的2个归并段再两两归并,得到有序文件
      请添加图片描述
  3. 外部排序的特点
    • 在外部排序中实现两两归并时,不仅要调用merge过程,而且要进行外存的读/写,因为不可能将两个有序段(归并段)及归并结果段同时存放在内存中。假设每个物理块可容纳200个记录( 50 × 200 = 10000 50\times 200=10000 50×200=10000),则每趟归并需要进行50次读和50次写,生成初始归并段+4趟归并就需要500次读写( 100 + 100 × 4 100+100\times 4 100+100×4)
    • 外部排序所需时间=内部排序(产生初始归并段)所需时间+外存信息读写时间+内部归并所需时间
      • 这其中,外存信息读写时间明显占时间大头,因此,提高外排的效率应主要着眼于减少外存信息读写的次数。而对于同一文件,这个读写次数和归并的趟数成正比,一般情况下,对m个初始归并段进行k-路平衡归并时,归并的趟数 s = ⌊ l o g k m ⌋ s=\lfloor log_km\rfloor s=logkm,可见若增加k或减少m,就能减少s
  4. 提高外部排序效率/减少外存信息读写时间/减少归并趟数:
    • 增加k:对于k个归并段一起归并,归并结果中的第一个记录就是k个归并段中关键字最小的记录,则得到归并结果中的每一个记录,都需要进行k-1次比较。因此随着k的增长,内部归并时间也增长,这将抵消由于增大k而减少外存信息读写时间所得效益。
      • 败者树:使得在k个记录中选出关键字最小的记录时仅需进行 ⌊ l o g 2 k ⌋ \lfloor log_2k\rfloor log2k次比较,从而使总的内部归并时间减少。(之前从k个记录选择一个最小的需要k-1次)。
      • 败者树是一个完全二叉树,k个叶节点分别对应k个归并段中当前参加比较的元素,非叶子节点用来记忆左右子树中的失败者,而让胜者往上继续比较,一直到根节点
      • 如下图,方形节点表示叶子节点(或外节点),分别为5个归并段中当前参加归并的记录的关键字;根节点ls[1]的双亲节点ls[0]为冠军(最小关键字记录);节点ls[3]指示b1和b2两个叶子节点中的败者即b2,而胜者b1和b3进行比较,节点ls[1]指示它们中的败者为b1。在选择最小关键字的记录之后,只要修改叶子节点b3中的值,使其为同一归并段中的下一个记录的关键字,然后从该节点向上和双亲节点所指的关键字进行比较,败者留在该双亲节点,胜者继续向上直至树根的双亲。
        请添加图片描述
    • 减少m:m是外部文件经过内部排序之后得到的初始归并段的个数, m = ⌈ n l ⌉ m=\lceil \frac{n}{l} \rceil m=ln n n n为外部文件中的记录数, l l l为初始归并段中的记录数)。 l l l的大小完全依赖于进行内部排序时可用内存工作区的大小。
      • 置换选择排序:FI为初始待排文件,FO为初始归并段文件,WA为内存工作区,FO和WA的初始状态为空,并设内存工作区WA的容量可容纳 w w w个记录,MINIMAX记录为从WA中选出的最小的记录
        • 在WA中选择MINIMAX记录的过程是利用败者树来实现的:WA中的记录作为败者树的外部节点,而败者树中根节点的双亲节点指示工作区中关键字最小的记录。
        • 由置换选择排序所得初始归并段的长度不等
        • 若不计输入、输出的时间,则对n个记录的文件而言,生成所有初始归并段所需时间为 O ( n l o g w ) O(nlogw) O(nlogw)
    • 最佳归并树:由置换-选择生成所得的m个初始归并段,构造一棵哈夫曼树作为归并树,即可使在进行外部归并时所需对外存进行的读/写次数达最少。当初始归并段的数目不足时,需附加长度为0的“虚段”
      • 对于k-路归并,m个初始归并段,若 ( m − 1 ) M O D ( k − 1 ) = 0 (m-1)MOD(k-1)=0 (m1)MOD(k1)=0,则不需要加虚段,否则需要附加 k − ( m − 1 ) M O D ( k − 1 ) − 1 k-(m-1) MOD (k-1)-1 k(m1)MOD(k1)1个虚段,即,第一次归并为 ( m − 1 ) M O D ( k − 1 ) + 1 (m-1) MOD (k-1) +1 (m1)MOD(k1)+1路归并

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

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

相关文章

cola架构:cola源码中访问者模式应用浅析

目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道&#xff0c;如果一个对象结构包含很多类型的对象&#xff0c;希望对这些对象实施一些依赖其具体类型的操作&#xff0c;但又避免让这些操作“污染”这些对象的类&#xff0c…

如何使用爬虫做一个网站

​ 大家如果有兴趣做网站&#xff0c;在买了VPS&#xff0c;部署了wordpress&#xff0c;配置LNMP环境&#xff0c;折腾一番却发现内容提供是一个大问题&#xff0c;往往会在建站的大&#xff08;da&#xff09;道&#xff08;keng&#xff09;上泄气 &#xff0c;别怕&#xf…

java毕业设计基于springboot的民宿预订信息网站

运行环境 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven 项目介绍 民宿短租…

iPhone强制重启教程来了!(已解决)

强制重启是解决苹果手机系统故障问题的首选操作&#xff0c;是通过特殊组合按键来强制关机并重新启动设备的操作。可以用来应对系统崩溃、设备无响应、白苹果、死机、闪退、莫名其妙黑屏等情况。 那么大家知道该如何将iPhone手机强制重启吗&#xff1f;iphone强制重启的方法是…

电脑上怎么录制视频教程带画笔工具?

无论你是创建教程、还是演示文稿&#xff0c;可能都希望使用带有画笔工具的录屏软件来帮助你创建吸引观众注意力的重要内容。幸运的是&#xff0c;有一些很棒的录屏软件可供你选择&#xff0c;本文就为你推荐一款带有画笔工具的最佳录屏软件&#xff0c;继续阅读查看吧&#xf…

日本IT Week秋季展丨美格智能以技术创新共建美好数字生活

10月25日至27日&#xff0c;日本国际IT消费电子展览会&#xff08;Japan IT Week 2023秋季展&#xff09;在日本千叶幕张国际展览中心举行。日本IT周是日本IT市场的标杆&#xff0c;涵盖软件开发、大数据管理、嵌入式系统、数据存储、信息安全、数据中心、云计算、物联网&#…

Wappalyzer——非常好用的前端工具

Edge浏览器https://microsoftedge.microsoft.com/addons/detail/wappalyzer-technology-p/mnbndgmknlpdjdnjfmfcdjoegcckoikn谷歌浏览器https://chrome.google.com/webstore/detail/wappalyzer-technology-pro/gppongmhjkpfnbhagpmjfkannfbllamg火狐浏览器https://addons.mozil…

【Django restframework】django跨域问题,解决PUT/PATCH/DELETE用ajax请求无法提交数据的问题

【Django restframework】django跨域问题&#xff0c;解决PUT/PATCH/DELETE用ajax请求无法提交数据的问题 1 问题描述&#xff1a; 我用restframework(ModelSerializerGenericApiView)开发了一组符合RestFul接口标准的接口&#xff0c;这意味着它将支持客户端发来的GET、POST、…

Redis实现方式开启新篇章,解决分布式环境下的资源竞争问题,提升系统稳定性

前言 分布式锁一般有三种实现方式&#xff1a; 数据库乐观锁&#xff1b;基于Redis的分布式锁&#xff1b;基于ZooKeeper的分布式锁 本篇博客将介绍第二种方式&#xff0c;基于Redis实现分布式锁。 虽然网上已经有各种介绍Redis分布式锁实现的博客&#xff0c;然而他们的实…

飞桨大模型套件:一站式体验,性能极致,生态兼容

在Wave Summit 2023深度学习开发者大会上&#xff0c;来自百度的资深研发工程师贺思俊和王冠中带来的分享主题是&#xff1a;飞桨大模型套件&#xff0c;一站式体验&#xff0c;性能极致&#xff0c;生态兼容。 大语言模型套件PaddleNLP 众所周知PaddleNLP并不是一个全新的模型…

微服务-Ribbon负载均衡

文章目录 负载均衡原理流程原理源码分析负载均衡流程 负载均衡策略饥饿加载总结 负载均衡原理 流程 原理 LoadBalanced 标记RestTemplate发起的http请求要被Ribbon进行拦截和处理 源码分析 ctrlshiftN搜索LoadBalancerInterceptor&#xff0c;进入。发现实现了ClientHttpRequ…

电脑扬声器未插入?4个方法帮你恢复声音!

“太奇怪了吧&#xff0c;我的电脑扬声器一直显示未插入&#xff0c;我使用电脑的时候也是一直都没有声音。这是为什么呢&#xff1f;我应该怎么解决这个问题呀&#xff1f;” 我们使用电脑播放音频或视频时&#xff0c;都需要用到电脑扬声器。如果扬声器无法播放声音&#xff…

导入Embassy库进行爬虫

Embassy是一个基于Lua的轻量级爬虫框架&#xff0c;可以方便地进行网页抓取和数据提取。它提供了简单易用的接口和丰富的功能&#xff0c;可以帮助开发者快速构建爬虫应用。 要使用Embassy进行爬虫&#xff0c;首先需要安装Embassy库。可以通过Lua的包管理工具luarocks来安装E…

LabVIEW应用开发——控件的使用(四)

接上文&#xff0c;这篇介绍时间控件。 LabVIEW应用开发——控件的使用&#xff08;三&#xff09; 1、时间控件Time Stamp control 在日常软件开发场景中&#xff0c;时间也是一种常用的控件&#xff0c;用于表达当前时间的显示、对下设置时间、时间同步等等场景。LabVIEW专门…

『C语言进阶』文件操作

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f516;系列专栏&#xff1a; C语言、Linux、Cpolar ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、什么是文件1.1 程序文件1.2 数据文件1.3 文件名 二、文件的打开和关闭2.1 文件指针2.2 文件的打开和关…

[计算机提升] Windows文件系统类型介绍

1.13 文件系统 在Windows系统中&#xff0c;文件系统是一种用于组织和管理计算机上存储的文件和目录的方法。它提供了一种结构化的方式来访问、存储和检索数据。 以下是Windows系统中常见的文件系统&#xff1a; FAT&#xff08;FAT16、FAT32&#xff09;&#xff1a;FAT&…

超简洁ubuntu linux 安装 cp2k

文章目录 打开下载网址解压接下来的步骤讲解 将解压的包移到对应路径下最后运行 打开下载网址 需要从github下载&#xff1a;下载网址 两个都可以从windows下先下载&#xff0c;再复制到linux中&#xff0c; 如果不能复制&#xff0c;右键这两个&#xff0c;复制链接&#xf…

【开源】基于SpringBoot的农村物流配送系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

Redis快速上手篇(四)(Spring Cache,缓存配置)(注解方式)

Spring Cache 从3.1开始&#xff0c;Spring引入了对Cache的支持。其使用方法和原理都类似于Spring对事务管理的支持。Spring Cache是作用在方法上的 使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。 使用Spring Cache需要我们做两方面…

电子学会C/C++编程等级考试2023年05月(三级)真题解析

C/C等级考试&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;找和为K的两个元素 在一个长度为n(n < 1000)的整数序列中&#xff0c;判断是否存在某两个元素之和为k。 输入 第一行输入序列的长度n和k&#xff0c;用空格分开。 第二行输入序列中的n个整数&am…