【数据结构(邓俊辉)学习笔记】列表04——排序器

文章目录

  • 0. 统一入口
  • 1. 选择排序
    • 1.1 构思
    • 1.2 实例
    • 1.3 实现
    • 1.4 复杂度
  • 2. 插入排序
    • 2.1 构思
    • 2.2 实例
    • 2.3 实现
    • 2.4 复杂度分析
    • 2.5 性能分析
  • 3. 归并排序
    • 3.1 二路归并算法
      • 3.1.1 二路归并算法原理
      • 3.1.2 二路归并算法实现
      • 3.1.3 归并时间
    • 3.2 分治策略
      • 3.2.1 实现
      • 3.2.2 排序时间
  • 4. 总结

0. 统一入口

设置一个统一的排序操作接口。

template <typename T>
void List<T>::sort ( ListNodePosi(T) p, int n ) { //列表区间排序
	switch ( rand() % 3 ) { //随机选择排序算法。可根据具体问题的特点灵活选择或扩充
		case 1: insertionSort ( p, n ); break; //插入排序
		case 2: selectionSort ( p, n ); break; //选择排序
		default: mergeSort ( p, n ); break; //归并排序
	}
}

1. 选择排序

1.1 构思

在这里插入图片描述
在任何时刻,后缀S[r, n)已经有序,且不小于前缀S[0, r)

起泡排序需要O( n 2 n^2 n2)时间,因为挑选每个最大元素M,需做O(n)次比较和O(n)次交换。

1.2 实例

在这里插入图片描述

1.3 实现

在这里插入图片描述
算法思想:
算法迭代过程如图所示,已排序区间S[T,p+n),未排序区间U[p,T)。在未排序区间使用selectMax()接口定位最大节点,放入已排序区间。

template <typename T> //对列表中起始于位置p、宽度为n的区间做选择排序
void List<T>::selectionSort( ListNodePosi<T> p, Rank n ) { // valid(p) && Rank(p) + n <= size
   ListNodePosi<T> head = p->pred, tail = p;
   for ( Rank i = 0; i < n; i++ ) tail = tail->succ; //待排序区间为(head, tail)
   while ( 1 < n ) { //在至少还剩两个节点之前,在待排序区间内
      ListNodePosi<T> max = selectMax ( head->succ, n ); //找出最大者(歧义时后者优先)
      insert( remove( max ), tail ); //将其移至无序区间末尾(作为有序区间新的首元素)
      tail = tail->pred; n--;
   }
}

推敲:selectionSort() 算法中insert()和remove()反复new 和delete操作,此操作虽然视为常数复杂度但时间消耗时间大概为基本操作的100倍。

优化思路:

  1. 只通过对M和T两处局部引用的修改来实现同样的功能。
  2. 只需交换M和T前驱节点的数据域。

在这里插入图片描述

template <typename T> //从起始于位置p的n个元素中选出最大者
ListNodePosi<T> List<T>::selectMax( ListNodePosi<T> p, Rank n ) {
   ListNodePosi<T> max = p; //最大者暂定为首节点p
   for ( ListNodePosi<T> cur = p; 1 < n; n-- ) //从首节点p出发,将后续节点逐一与max比较
      if ( !lt( ( cur = cur->succ )->data, max->data ) ) //若当前元素不小于max,则
         max = cur; //更新最大元素位置记录
   return max; //返回最大节点位置
}

插入和删除算法见列表02——无序列表。

lt 为 ”≥“ ,遇到重复元素时,返回秩最大者,保证算法的稳定性。

1.4 复杂度

在这里插入图片描述
θ( n 2 n^2 n2)的效率应有很大的改进空间。

2. 插入排序

2.1 构思

在这里插入图片描述

2.2 实例

在这里插入图片描述

2.3 实现

在这里插入图片描述
算法思想:前缀S[0, r)已经有序。接下来,借助有序序列的查找算法,可在该前缀中定位到不大于e的最大元素。于是只需将e从无序后缀中取出,并紧邻于查找返回的位置之后插入,使得有序前缀的范围扩大至S[0, r]。

template <typename T> //对列表中起始于位置p、宽度为n的区间做插入排序
void List<T>::insertionSort( ListNodePosi<T> p, Rank n ) { // valid(p) && Rank(p) + n <= size
   for ( Rank r = 0; r < n; r++ ) { //逐一为各节点
      insert( search( p->data, r, p ), p->data ); //查找适当的位置并插入
      p = p->succ; remove( p->pred ); //转向下一节点
   }
}

在这里插入图片描述

2.4 复杂度分析

插入操作和删除操作均只需O(1)时间。查找操作search()所需时间可在O(1)至O(n)之间浮动。

当输入序列已经有序时,该算法中的每次search()操作均仅需O(1)时间,总体运行时间为O(n)。但反过来,若输出序列完全逆序,则各次search()操作所需时间将线性递增,累计共需O( n 2 n^2 n2)时间。在等概率条件下,平均仍需要O( n 2 n^2 n2)时间,换而言之,最好情况发生概率极低。

2.5 性能分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结论:
在等概率条件下,平均仍需要O( n 2 n^2 n2)时间。

  • 假定序列中 n 个元素的数值为独立均匀地随机分布,以下结论成立:
  1. 列表的插入排序算法平均需做约 n 2 / 4 = O ( n 2 ) n^2/4 = O(n^2) n2/4=O(n2)次元素比较操作;
  2. 向量的插入排序算法平均需做约 n 2 / 4 = O ( n 2 ) n^2/4 = O(n^2) n2/4=O(n2)次元素移动操作;
  3. 序列的插入排序算法过程中平均有 expected-O(logn)个元素无需移动。

3. 归并排序

3.1 二路归并算法

3.1.1 二路归并算法原理

有序列表的二路归算法同二路归并的向量排序算法,见 向量05——排序器 。能够达到与有序向量二路归并同样高的效率。
在这里插入图片描述

3.1.2 二路归并算法实现

算法思想:List::merge()可以将另一有序列表L中起始于节点q、长度为m的子列表,与当前有序列表中起始于节点p、长度为n的子列表做二路归并。

template <typename T> //有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并
ListNodePosi<T> List<T>::merge( ListNodePosi<T> p, Rank n,List<T>& L, ListNodePosi<T> q, Rank m ) {
   ListNodePosi<T> pp = p->pred; //归并之后p可能不再指向首节点,故需先记忆,以便在返回前更新
   while ( ( 0 < m ) && ( q != p ) ) //q尚未出界(或在mergeSort()中,p亦尚未出界)之前
      if ( ( 0 < n ) && ( p->data <= q->data ) ) //若p尚未出界且v(p) <= v(q),则
         { p = p->succ; n--; } //p直接后移,即完成归入
      else //否则,将q转移至p之前,以完成归入
         { insert( L.remove( ( q = q->succ )->pred ), p ); m--; }
   return pp->succ; //更新的首节点
}

3.1.3 归并时间

        ~~~~~~~        merge()的时间成本主要消耗于其中的迭代,当且仅当后一子列表中所有节点均处理完毕时,迭代才会终止。因此,在最好情况下,共需迭代m次;而在最坏情况下,则需迭代n次。
        ~~~~~~~        总体而言,共需O(n + m)时间,线性正比于两个子列表的长度之和。

3.2 分治策略

3.2.1 实现

在这里插入图片描述

template <typename T> //列表的归并排序算法:对起始于位置p的n个元素排序
void List<T>::mergeSort( ListNodePosi<T>& p, Rank n ) { // valid(p) && Rank(p) + n <= size
   if ( n < 2 ) return; //若待排序范围已足够小,则直接返回;否则...
   Rank m = n >> 1; //以中点为界
   ListNodePosi<T> q = p; for ( Rank i = 0; i < m; i++ ) q = q->succ; //找到后子列表起点
   mergeSort( p, m ); mergeSort( q, n - m ); //前、后子列表各分别排序
   p = merge( p, m, *this, q, n - m ); //归并
} //注意:排序后,p依然指向归并后区间的(新)起点

3.2.2 排序时间

在子序列的划分阶段,向量与列表归并排序算法之间存在细微但本质的区别。前者支持循秩访问的方式,故可在O(1)时间内确定切分中点;后者仅支持循位置访问的方式,故不得不为此花费O(n)时间。幸好在有序子序列的合并阶段二者均需O(n)时间,故二者的渐进时间复杂度依然相等O(nlogn)。

尽管二路归并算法并未对子列表的长度做出任何限制,但这里出于整体效率的考虑,在划分子列表时宁可花费O(n)时间使得二者尽可能接近于等长。反之,若为省略这部分时间而不保证划分的均衡性,则反而可能导致整体效率的下降。

结论:
若为节省每次子列表的划分时间,而直接令 m = min(c, n/2),其中 c 为较小的常数(比如 5),则总体复杂度反而会上升至 O( n 2 n^2 n2)。
在这里插入图片描述

4. 总结

  1. 选择排序:U[o,r) + S[r,n)。从未排序元素中挑选最大者并使之就位。时间复杂度为θ( n 2 n^2 n2),移动操作远远小于起泡排序。
  2. 插入排序:S[o,r) + U[r,n)。从未排序元素中挑选最大者并使之就位。输入敏感型算法,最好情况1次比较,0次交换,累计O(n)时间(发生概率低)。最坏情况第k次迭代,需O(k)次比较,1次交换,累计O( n 2 n^2 n2)时间。
  3. 归并排序:前提是在划分子列表时宁可花费O(n)时间使得二者尽可能接近于等长,渐进复杂度为O(nlogn)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记:【QC】Android Q - IMS 模块

一、IMS init 流程图 二、IMS turnon 流程图 三、分析说明 1、nv702870 不创建ims apn pdp 2、nv702811 nv702811的时候才创建ims pdp&#xff1a; ims pdp 由ims库发起&#xff0c;高通没有开放这部分代码&#xff1a; 10-10 11:45:53.027 943 943 E Diag_Lib: [IMS_D…

只用语音能训练出AI大模型吗?就像训练会说话但不识字的人一样

AI语音对话技术通常是基于语音识别和自然语言处理&#xff08;NLP&#xff09;的。在这个过程中&#xff0c;语音首先被识别成文字&#xff0c;然后NLP技术对这些文字进行处理&#xff0c;生成回应。然而&#xff0c;我们是否可以直接训练一个“文盲”大模型&#xff0c;即只用…

45. UE5 RPG 增加角色受击反馈

在前面的文章中&#xff0c;我们实现了对敌人的属性的初始化&#xff0c;现在敌人也拥有的自己的属性值&#xff0c;技能击中敌人后&#xff0c;也能够实现血量的减少。 现在还需要的就是在技能击中敌人后&#xff0c;需要敌人进行一些击中反馈&#xff0c;比如敌人被技能击中后…

深度学习中的注意力机制二(Pytorch 16)

一 Bahdanau 注意力 通过设计一个 基于两个循环神经网络的编码器‐解码器架构&#xff0c;用于序列到序列学习。具体来说&#xff0c;循环神经网络编码器将长度可变的序列转换为固定形状的上下文变量&#xff0c;然后循环神经网络 解码器根据生成的词元和上下文变量按词元生成…

meshlab: pymeshlab计算两个模型的布尔交集(mesh boolean intersection)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本案例以两个圆环为例。 左侧为两个圆环&#xff0c;右上是重叠&#xff0c;右下是圆…

引流源码短剧搜索前端源码+内附搜索API

引流源码短剧搜索前端源码内附搜索API&#xff0c;全网短剧搜索前端源码分享&#xff0c;文末附API及使用详解 内含7000短剧资源(不支持在线播放&#xff09;&#xff0c;毕竟搞在线播放挺烧钱的[阴险] 源码直接上传虚拟主机或服务器即可使用&#xff0c;无需其他配置&#x…

jvm 马士兵 01 JVM简介,class文件结构

01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件&#xff0c;符合JVM规范的class文件都可以被识别 u1 是一个字节 u2是两个字节

使用网络用户命令行工具的/passwordreq:yes

提示:"新建域时&#xff0c;本地administrator帐户将成为域administrator账户。无法新建域&#xff0c;因为本地administrator账户密码不符合要求。 目前&#xff0c;本地administrator账户不需要密码。我们建议您使用网络用户命令行工具的/passwordreq:yes选项获得该账户…

AI图书推荐:ChatGPT在真实商业世界中的应用

《ChatGPT在真实商业世界中的应用》 (Unleashing The Power of ChatGPT: A Real World Business Applications)首先概述了ChatGPT及其在对话式人工智能领域的影响。接着&#xff0c;你将深入了解ChatGPT的技术方面&#xff0c;理解机器学习算法和自然语言处理如何在后台工作。然…

鸿蒙ArkTs开发,仿抖音个人中心header 下拉放大

如果是iOS 或者android 上实现&#xff0c;可以用Scollview 的contentOffset 来实现&#xff0c;然而在鸿蒙ets中该如何实现&#xff1f;废话不多说开始撸代码 第一步、实现一个header // 创建header&#xff0c;准备一张背景图片BuilderHeaderBuilder(){Column() {Row() {Ima…

社交媒体数据恢复:爱聊

爱聊数据恢复方法 在爱聊的使用过程中&#xff0c;如果遇到数据丢失的情况&#xff0c;可以尝试以下几种方法来恢复数据。 1. 硬盘坏道检测与修复 如果问题是由于硬盘坏道导致的&#xff0c;可以按照以下步骤进行操作&#xff1a; 找到需要修复的坏道磁盘&#xff1a;首先&…

js模块化:修改导入模块的内容,会有影响吗?

起因 element-ui的popper组件相关的层级&#xff0c;是使用popup-manager来统一管理的。 之前试图在自己的组件里导入并使用element-ui的popup-manager&#xff0c;但是层级老是和element-ui组件的层级冲突&#xff0c;看了下源码&#xff0c;竟意外发现&#xff0c;使用popu…

基于若依框架搭建网站的开发日志(一):若依框架搭建、启动、部署

RuoYi&#xff08;基于SpringBoot开发的轻量级Java快速开发框架&#xff09; 链接&#xff1a;开源地址 若依是一款开源的基于VueSpringCloud的微服务后台管理系统&#xff08;也有SpringBoot版本&#xff09;&#xff0c;集成了用户管理、权限管理、定时任务、前端表单生成等…

You don’t have permission.

The document “XXX” could not be saved. You don’t have permission. 1.查看修改了iOS系统库导致的, 根据提示, 进入到"XXX"文件中, 然后commandz回退/取消 2. Xcode 调试遇到的报错&#xff08;持续更新&#xff09;

治疗耳鸣患者案例分享第二期

“患者耳鸣20年了&#xff0c;目前耳朵没有堵或者胀的感觉&#xff0c;但是偶尔有点痒&#xff0c;平时会有头晕头胀这种情况&#xff0c;然后头晕是稍微晕炫一下。然后头疼是经常有的&#xff0c;头胀不经常。” 患者耳鸣持续20年&#xff0c;虽然耳朵没有堵或胀的感觉&#x…

书生浦语训练营第三次课笔记:XTuner 微调 LLM:1.8B、多模态、Agent

Finetune 简介 两种Finetune范式&#xff1a;增量预训练微调、指令跟随微调 微调数据集 上述是我们所期待模型回答的内容&#xff0c;在训练时损失的计算也是基于这个。 训练数据集看起来是这样&#xff0c;但是真正喂给模型的&#xff0c;是经过对话模板组装后的 下图中&…

防火墙的基本概念

我们在 TCP/IP协议四层模型与OSI七层模型 的最后说过&#xff0c;在四层模型中每一层都会有对应的风险&#xff0c;而防火墙就是来阻断这些风险的工具。 防火墙的基本功能 防火墙的分类 目前没有权威而明确的分类 按照实现方式&#xff1a; 硬件防火墙软件防火墙 按照部署…

HNU-人工智能-实验1-A*算法

人工智能-实验1 计科210x 甘晴void 一、实验目的 掌握有信息搜索策略的算法思想&#xff1b; 能够编程实现搜索算法&#xff1b; 应用A*搜索算法求解罗马尼亚问题。 二、实验平台 课程实训平台https://www.educoder.net/shixuns/vgmzcukh/challenges 三、实验内容 3.…

高扬程水泵助力森林消防,守护绿色生命线/恒峰智慧科技

随着人类社会的不断发展&#xff0c;森林资源的保护和管理变得越来越重要。然而&#xff0c;森林火灾却时常威胁着这一宝贵资源。为了有效应对森林火灾&#xff0c;提高灭火效率&#xff0c;高扬程水泵在森林消防中发挥了重要作用。本文将重点介绍高扬程水泵在森林消防中的应用…

AI终端设备的自动化分级

摘要&#xff1a; AI智体被定义为感知环境、做出决策和采取行动的人工实体。 受SAE&#xff08;汽车工程师学会&#xff09;自动驾驶6个级别的启发&#xff0c;AI智体也根据效用和强度进行分类&#xff0c;分为以下几个级别&#xff1a; L0——无AI&#xff0c;有工具&#xf…
最新文章