排序整理2

news2024/11/16 15:57:07

一、一些概念

  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.coloradmin.cn/o/1139341.html

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

相关文章

直播切片想要快速批量制作应该怎么做?

账号准备是启动直播切片的第一步。要求账号拥有1000粉丝并完成实名认证&#xff0c;因为只有达到1000粉才能开通橱窗进行带货。这是最基本的要求。 接下来是获得授权。与大IP工作室合作并取得授权是免费的&#xff01;在每个大IP工作室或切片授权号上留意统一的授权对接时间&a…

GoLong的学习之路(十一)语法之标准库 fmt.Printf的使用

上回书说到&#xff0c;函数&#xff0c;说了函数是如何实现的&#xff0c;高级函数有哪几种调用方式&#xff0c;本章我将介绍fmt 标准库中我常用的一些函数。 文章目录 fmtfmt的向外输出print格式化占位通用占位符布尔类型占位整型占位浮点数与复数字符串和[]byte指针宽度表示…

阿里巴巴:海量请求下的接口并发,都有哪些方案?

设定一个场景&#xff0c;假如一个电商商品封装API接口在某段时间突然上升&#xff0c;会怎么办&#xff1f; 生活中的例子来说&#xff0c;假设冰墩墩在当天晚上上热搜之后&#xff0c;迅速有十几万人去淘宝下单购买&#xff0c;此时并没有做好对该商品的缓存预热以及准备&am…

华为OD机试 - 滑动窗口最大和 - 滑动窗口(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

Java数据类型,变量与运算符

1.字面常量 常量是在程序运行期间&#xff0c;固定不变的量称为常量。 public class HelloWorld{public static void main(String[] args){System.out.println("Hello,world");} } 在以上程序中&#xff0c;输出的Hello Word&#xff0c;其中的“Hello Word”就是…

Go语言的Mutex

在本教程中&#xff0c;我们将了解互斥体。我们还将学习如何使用互斥体和通道解决竞争条件。 关键部分 在跳转到互斥体之前&#xff0c;了解并发编程中临界区的概念非常重要。当程序并发运行时&#xff0c;修改共享资源的代码部分不应被多个Goroutines同时访问。这部分修改共…

Delft3D水动力-富营养化模型实践技术高级应用

湖泊富营养化等水质问题严重威胁我国经济社会的发展&#xff0c;也是水环境和水生态领域科研热点之一。水环境模型是制定湖泊富营养化控制对策&#xff0c;预测湖泊水环境发展轨迹的重要工具&#xff0c;在环境影响评价、排污口论证等方面也有着广泛的应用。荷兰Delft研究所开发…

腾讯云轻量应用服务器性能如何?来自学生的评价

腾讯云轻量应用服务器怎么样&#xff1f;CPU性能如何&#xff1f;我们班同学人手一台&#xff0c;轻量服务器简单高效快速部署&#xff0c;不限制CPU性能&#xff0c;并且费用很低&#xff0c;很适合我们这种群生群体。可以的话&#xff0c;可以推出一些适合学生用户的GPU实例&…

二叉树问题——验证二叉搜索树

摘要 98. 验证二叉搜索树 一、验证二叉搜索树解析 给定一个二叉树&#xff0c;判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征&#xff1a; 节点的左子树只包含小于当前节点的数。节点的右子树只包含大于当前节点的数。所有左子树和右子树自身必须也是…

何为自制力?如何提高自制力?

什么是自制力&#xff1f; 自制力也即是自我控制能力&#xff0c;是一个人如何去抵御外部诱惑力&#xff0c;从而坚持自己的原本计划&#xff0c;坚定去完成目标。除了外部诱惑力&#xff0c;也可以指的是面对困境&#xff0c;不良情绪等外部因素。 自制力是自我管理能力的体…

【Qt】文件系统

文章目录 文件系统文件操作案例&#xff1a;显示路径到标题框&#xff0c;显示内容到文本框对文件进行写操作获取文件相关信息 文件系统 Qt 通过QIODevice提供了对 I/O 设备的抽象&#xff0c;这些设备具有读写字节块的能力&#xff0c;下面是 I/O 设备的类图&#xff1a; QIO…

【Proteus仿真】【STM32单片机】智能助眠机系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用蜂鸣器闹铃模块、LCD1602显示模块、心率血氧模块、PCF8691 ADC模块、按键模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示传…

【开源】基于SpringBoot的高校学院网站的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学院院系模块2.2 竞赛报名模块2.3 教育教学模块2.4 招生就业模块2.5 实时信息模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学院院系表3.2.2 竞赛报名表3.2.3 教育教学表3.2.4 招生就业表3.2.5 实时信息表 四、系…

校园门禁升级改造,终于看到了希望!

随着社会的不断发展和技术的日益进步&#xff0c;安全和访问控制成为了各种场所和组织的首要关切。门禁监控系统作为一种融合了物理安全与电子监控的创新解决方案&#xff0c;已经成为了现代社会不可或缺的一部分。 客户案例 企业办公楼 福州某企业办公楼公司采用了泛地缘科技…

【开源】基于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;…

Spring源码-3.Bean的后置处理器

Bean后置处理器与注解的关系 首先以一个没有添加额外的后置处理器来说明&#xff1a;️GenericApplicationContext GenericApplicationContext context new GenericApplicationContext();public class Bean1 {private static final Logger log LoggerFactory.getLogger(Bea…

工作流审批平台,可迁移,可快速开发审批单(源码)

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端分离部署开发模式&#xff0c;快速开发平…

vscode C++项目相对路径的问题

如图所示的项目目录结构 如果要在main.cpp里用相对路径保存一个txt文件 std::ofstream file("./tree_model/my_file.txt");if (file.is_open()) {file << "This is a sample text.\n";file.close();std::cout << "File saved in the mode…

stm32 Keil V5 开发pack突然丢失

1.好好的工程,前一天可以正常编译,第二天突然无法编译,显示缺少安装包文件,如是重新下载安装包进入导入。 2.显示丢失 1.做STM32开发时,经常发现下载的DEMO代码无法打开,ST自带的更新库软件根本连不上服务器,每次到此都非常恼火。 3. CMSIS变成可红色 2. 莫名其妙的丢…

通过servlet设计一个博客系统

博客系统 准备工作servlrt依赖mysql依赖jackson依赖 服务器和数据库的交互设计数据库/数据表封装DBUtil,实现建立连接和断开连接创建实体类bloguser 编写Dao类BlogDaoUserDao 前端和服务器的交互功能一:博客列表页约定格式后端代码前端代码 功能二:实现博客详情页约定格式后端代…