【数据结构(邓俊辉)学习笔记】列表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 <= sizeListNodePosi<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; //最大者暂定为首节点pfor ( 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 <= sizefor ( 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 <= sizeif ( 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.mzph.cn/web/6897.shtml

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

相关文章

【Java】基本程序设计结构(二)

前言&#xff1a;上一篇我们详细介绍了Java基本程序设计结构中前半部分&#xff0c;一个简单的Java应用&#xff0c;注释&#xff0c;数据类型&#xff0c;变量与常量&#xff0c;运算符&#xff0c;字符串。包括本篇将延续上篇内容介绍后续内容&#xff0c;包括输入输出&#…

AutoTable, Hibernate自动建立表替代方案

痛点 之前一直使用JPA为主要ORM技术栈&#xff0c;主要是因为Mybatis没有实体逆向建表功能。虽然Mybatis有从数据库建立实体&#xff0c;但是实际应用却没那么美好&#xff1a;当实体变更时&#xff0c;往往不会单独再建立一个数据库重新生成表&#xff0c;然后把表再逆向为实…

渠道管控治理思路建议

品牌在做控价时&#xff0c;一定要有渠道一体化的治理想法&#xff0c;不能只能打击某一家店铺为想法进行治理&#xff0c;比如只打击非授权&#xff0c;只不去管理授权体系的经销商店铺&#xff0c;这显然是不行的&#xff0c;管理非授权的同时&#xff0c;授权也要管理好&…

QT+串口调试助手+扩展版

前言&#xff1a;此文章是这篇文章的拓展 QT串口调试助手基本版-CSDN博客&#xff0c;如果需要独立完成串口调试助手直接看基本版文章即可&#xff0c;如果需要完成串口调试助手的其他功能&#xff0c;参考拓展版。 一、更新QT串口调试助手UI界面 1、ui串口设置界面 2、ui串口…

华为OD机试【求满足条件的最长子串的长度】(java)(100分)

1、题目描述 给定一个字符串&#xff0c;只包含字母和数字&#xff0c;按要求找出字符串中的最长&#xff08;连续&#xff09;子串的长度&#xff0c;字符串本身是其最长的子串&#xff0c;子串要求&#xff1a; 只包含1个字母(a-z, A-Z)&#xff0c;其余必须是数字&#xf…

Istio基础知识

一、什么是Istio Istio 提供⼀种简单的⽅式来为已部署的服务建⽴⽹络&#xff0c;该⽹络具有 负载均衡、服务间认证、监控等功能&#xff0c;只需要对服务的代码进⾏⼀点或不需要做任何改动。想要让服务⽀持 Istio&#xff0c;只需要在您的环境中部署⼀个特殊的 sidecar 代 理&…

工程技术SCI期刊,中科院3区,IF=3+,收稿范围广泛!

一、期刊名称 International Journal of Critical Infrastructure Protection 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;工程技术 影响因子&#xff1a;3.6 中科院分区&#xff1a;3区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;…

【JavaEE 初阶(二)】线程安全问题

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多线程知识 目录 1.前言2.synchronized2.1例子2.2synchronized修饰代码块2.3 synchronized修饰方法2.4sy…

分布式领域计算模型及SparkRay实现对比

目录 一、分布式计算领域概览 二、Spark计算模型分析 三、Ray计算模型分析 3.1 需求分析 3.2 系统设计 3.3 系统实现 四、总结 一、分布式计算领域概览 当前分布式计算模型主要分为以下4种&#xff1a; Bulk Synchronous Parallel Model&#xff08;块同步并行模型&…

【Linux 11】进程地址空间

文章目录 &#x1f308; Ⅰ 虚拟地址引入&#x1f308; Ⅱ 虚拟地址空间&#x1f308; Ⅲ 页表 (解释 fork() 的返回值既 > 0 又 0)&#x1f308; Ⅳ 什么是地址空间&#x1f308; Ⅴ 为什么要有地址空间 &#x1f308; Ⅰ 虚拟地址引入 现在通过一段代码来观察一个现象&a…

初识指针(1)<C语言>

前言 指针是C语言中比较难的一部分&#xff0c;大部分同学对于此部分容易产生“畏难情结”&#xff0c;但是学习好这部分对C语言的深入很大的帮助&#xff0c;所以此篇主要以讲解指针基础为主。 指针概念 变量创建的本质就是在内存中申请空间&#xff0c;找到这个变量就需要地址…

交互中的“互”难以产生的原因

脑机交互技术的目标是通过分析和解读大脑活动&#xff0c;将其与特定的意图、指令或行为连接起来。通过训练和分析&#xff0c;可以建立起大脑活动与特定行为或意图之间的关联模型&#xff0c;从而实现脑机交互的应用&#xff0c;例如控制外部设备、传递信息等。然而&#xff0…

Python机器学习实验 Python 数据可视化

1.实验目的 掌握 Matplotlib 数据可视化的常用方法。 2.实验内容 1. 绘制鸢尾花数据集的特征分布图 说明&#xff1a;鸢尾花是单子叶百合目花卉&#xff0c;是一种比较常见的花&#xff0c;鸢尾花的品种较多。 鸢尾花数据集最初由 Edgar Anderson 测量得到&#xff0c;而后在…

深入学习和理解Django模板层:构建动态页面

title: 深入学习和理解Django模板层&#xff1a;构建动态页面 date: 2024/5/5 20:53:51 updated: 2024/5/5 20:53:51 categories: 后端开发 tags: Django模板表单处理静态文件国际化性能优化安全防护部署实践 第一章&#xff1a;模板语法基础 Django模板语法介绍 Django模…

每天五分钟深度学习:数学中常见函数中的导数

本文重点 导数是微积分学中的一个核心概念,它描述了函数在某一点附近的变化率。在物理学、工程学、经济学等众多领域中,导数都发挥着极其重要的作用。本文旨在详细介绍数学中常见函数的导数,以期为读者提供一个全面而深入的理解。 数学中常见的导数 常数函数的导数 对于常数…

ctfshow 框架复现

文章目录 web 466web 467web 468web469web 470web 471web 472web 473web 474web 475web 476 web 466 Laravel5.4版本 &#xff0c;提交数据需要base64编码 代码审计学习—Laravel5.4 - 先知社区 (aliyun.com) 用第二条链子 反序列化格式 /admin/序列化串base64<?php na…

(论文阅读-多目标优化器)Multi-Objective Parametric Query Optimization

目录 摘要 一、简介 1.1 State-of-the-Art 1.2 贡献和大纲 二、定义 三、相关工作 四、问题分析 4.1 分析 4.2 算法设计影响 五、通用算法 5.1 算法概述 5.2 完备性证明 六、分段线性代价函数算法 6.1 数据结构 6.2 基本运算实现 6.3 复杂度分析 七、实验评估 …

FR-TSN4206获得“时间敏感网络产业链名录计划”测试认证证书,TSN交换机助力智能工业发展

TSN技术&#xff0c;即时间敏感网络技术&#xff0c;已成为智能工业、自动驾驶等领域的核心。它通过时钟同步、数据调度等功能&#xff0c;确保低延迟、高可靠性的数据传输。 为推动TSN技术在我国的发展&#xff0c;工业互联网产业联盟联合多家单位启动了“时间敏感网络产业链名…

Amazon EKS创建EFS存储卷

1、创建Amazon EFS CSI 驱动程序 亚马逊相关文档 在 Select trusted entity&#xff08;选择受信任的实体&#xff09;页面上操作 在 Add permissions&#xff08;添加权限&#xff09;页面上筛选AmazonEFSCSIDriverPolicy操作 记得将AmazonEBSVolumePolicy添加到我们创建的…

Colab/PyTorch - Getting Started with PyTorch

Colab/PyTorch - Getting Started with PyTorch 1. 源由2. 概要2.1 PyTorch是什么&#xff1f;2.2 为什么学习PyTorch&#xff1f;2.3 PyTorch库概览 3. 步骤4. 预期&展望5. 总结6. 参考资料 1. 源由 世界在发展&#xff0c;为其服务的技术也在不断演变。每个人都要跟上技…