【数据结构(邓俊辉)学习笔记】向量05——排序器

文章目录

  • 0. 概述
  • 1.统一入口
  • 2. 起泡排序
    • 2.1 起泡排序(基础版)
      • 2.1.1 算法分析
      • 2.1.2 算法实现
      • 2.1.3 重复元素与稳定性
      • 2.1.4 复杂度分析
  • 3. 归并排序
    • 3.1 有序向量的二路归并
    • 3.2 分治策略
    • 3.3 实例
    • 3.4 二路归并接口的实现
    • 3.5 归并时间
    • 3.6 排序时间
  • 4.综合评价

0. 概述

介绍下有序向量的排序器,包括起泡排序和归并排序。

1.统一入口

这类接口也是将无序向量转换为有序向量的基本方法和主要途径
在这里插入图片描述

2. 起泡排序

2.1 起泡排序(基础版)

2.1.1 算法分析

在这里插入图片描述

2.1.2 算法实现

反复调用单趟扫描交换算法,直至逆序现象完全消除。

template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort ( Rank lo, Rank hi ) //assert: 0 <= lo < hi <= size
{ while ( !bubble( lo, hi-- ) ); } //逐趟做扫描交换,直至全序

算法思想:依次比较各对相邻元素,每当发现逆序即令二者彼此交换;一旦经过某趟扫描之后未发现任何逆序的相邻元素,即意味着排序任务已经完成,则通过返回标志“sorted”,以便主算法及时终止。

template <typename T>
void Vector<T>::bubble ( Rank lo, Rank hi) { //0 <= nbool sorted = true; //整体排序标志while ( ++lo < hi ) { //自左向右,逐一检查各队相邻元素if ( _elem[lo - 1] > _elem[lo] ) { //若逆序,则sorted = false; //因整体排序不能保证,需要清除排序标志swap ( _elem[lo - 1], _elem[lo]); //交换}}return sorted;
} //借助布尔型标志位sorted,可及时提前退出,而不致总是蛮力地做n - 1趟扫描交换

2.1.3 重复元素与稳定性

稳定算法的特征是,重复元素之间的相对次序在排序前后保持一致。

该起泡排序过程中元素相对位置有所调整的唯一可能是,某元素_elem[i - 1]严格大于其后继_elem[i]。也就是说,在这种亦步亦趋的交换过程中,重复元素虽可能相互靠拢,但绝对不会相互跨越。由此可知,起泡排序属于稳定算法。

2.1.4 复杂度分析

在这里插入图片描述
如图,前r个元素无序,后n-r元素按顺序排列并严格就位。

bubble()算法由内、外两层循环组成。内循环从前向后,依次比较各对相邻元素,如有必要则将其交换。

扫描交换的趟数不会超过O( r ),算法总体消耗时间不会超过O(n *r)次。

故乱序元素仅限于 A[0, n \sqrt n n )区间,最坏情况下仍需调用 bubblesort1A ()做 Ω \Omega Ω( n \sqrt n n )次调用,共做 Ω \Omega Ω(n)次交换操作和 Ω \Omega Ω(n 3 2 ^{\frac 32} 23)次比较操作,因此累计运行 Ω \Omega Ω(n 3 2 ^{\frac 32} 23)时间。
该算法可进一步优化,详见算法设计优化——起泡排序

3. 归并排序

在这里插入图片描述

3.1 有序向量的二路归并

二路归并属于迭代式算法。每步迭代中,只需比较两个待归并向量的首元素,将小者取出并追加到输出向量的末尾,该元素在原向量中的后继则成为新的首元素。如此往复,直到某一向量为空。最后,将另一非空的向量整体接至输出向量的末尾。

在这里插入图片描述
二路归并算法在任何时刻只需载入两个向量的首元素,故除了归并输出的向量外,仅需要常数规模的辅助空间。

3.2 分治策略

算法思想:通过递归调用将二者分别转换为有序向量,即可借助二路归并算法,得到与原向量S对应的整个有序向量
在这里插入图片描述

template <typename T> //向量归并排序
void Vector<T>::mergeSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= sizeif ( hi - lo < 2 ) return; //递归基,单元素区间自然有序,否则...int mi = ( lo + hi ) >> 1; //以中点为界 mergeSort ( lo, mi ); //对前半段排序 mergeSort ( mi, hi ); //对后半段排序 merge ( lo, mi, hi ); //归并
}

3.3 实例

在这里插入图片描述

3.4 二路归并接口的实现

算法思想:创建临时数组B存放数组A的[ lo,mi)元素,数组C指向数组A的[mi,hi),调用二路归并算法,将有序向量存放在A中。在这里插入图片描述

template <typename T> //有序向量的归并
void Vector<T>::merge ( Rank lo, Rank mi, Rank hi ) { //各自有序的子向量[lo, mi)和[mi, hi)T* A = _elem + lo; //合并后的向量A[0, hi - lo) = _elem[lo, hi)int lb = mi - lo; T* B = new T[lb]; //前子向量B[0, lb) = _elem[lo, mi)for ( Rank i = 0; i < lb; B[i] = A[i++] ); //复制前子向量int lc = hi - mi; T* C = _elem + mi; //后子向量C[0, lc) = _elem[mi, hi)for ( Rank i = 0, j = 0, k = 0; ( j < lb ) || ( k < lc ); ) { //B[j]和C[k]中的小者续至A末尾if ( ( j < lb ) && ( ! ( k < lc ) || ( B[j] <= C[k] ) ) ) A[i++] = B[j++];if ( ( k < lc ) && ( ! ( j < lb ) || ( C[k] < B[j] ) ) ) A[i++] = C[k++];}delete [] B; //释放临时空间B
} //递归后得到完整的有序向量[lo, hi)
  • 若将后一句中的“C[k] < B[j]”改为“C[k] <= B[j]”,对算法将有何影响?

~~~~     经如此调整之后,虽不致影响算法的正确性(仍可排序),但不再能够保证各趟二路归并的稳定性,整个归并排序算法的稳定性也因此不能保证。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                  
~~~~     原算法的控制逻辑可以保证稳定性。实际上,若两个子区间当前接受比较的元素分别为B[j]和C[k],则唯有在前者严格大于后者时,才会将后者转移至A[i++];反之,只要前者不大于后者(包含二者相等的情况),都会优先转移前者。由此可见,无论是子区间内部(相邻)的重复元素,还是子区间之间的重复元素,在归并之后依然能够保持其在原向量中的相对次序。

  • 若将前一句中的“B[j] <= C[k]”改为“B[j] < C[k]”,对算法将有何影响?

当待归并的子向量之间有重复元素时,循环体内的两条处理语句均会失效,两个子向量的首
元素都不会被转移,算法将在此处进入死循环。

3.5 归并时间

在这里插入图片描述
二路归并只需线性时间的结论,并不限于相邻且等长的子向量。实际上,即便子向量在物理空间上并非前后衔接(列表),且长度相差悬殊,该算法也依然可行且仅需线性时间。

3.6 排序时间

在这里插入图片描述
故:
在这里插入图片描述

不足:
路归幵算法 merge(),反复地通过 new 和 delete 操作申请和释放辅助空间。然而实验统计表明,这类操作的实际时间成本,大约是常规运算的 100 倍,故往往成为制约效率提高的瓶颈。
改进点:
可以在算法启动时,统一申请一个足够大的缓冲区作为辅助向量B[],并作为全局变量为所有递归实例公用;归并算法完成之后,再统一释放。
如此可以将动态空间申请的次数降至O(1),而不再与递归实例的总数O(n)相关。当然,这样会在一定程度上降低代码的规范性和简洁性,代码调试的难度也会有所增加。

4.综合评价

  • 起泡排序最坏情况总需要O( n 2 n^2 n2)
  • 归并排序最坏情况下为O(nlogn)

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

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

相关文章

基于Matlab使用深度学习的多曝光图像融合

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在图像处理领域&#xff0c;多曝光图像融合技术是一种重要的技术&#xff0c;它可以将不同曝光条件下…

备忘录模式(行为型)

目录 一、前言 二、备忘录模式 三、总结 一、前言 备忘录模式(Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff0c;这样可以在之后将该对象恢复到原…

idea生成双击可执行jar包

我这里是一个生成xmind,解析sql的一个main方法,可以通过配置文件来修改有哪些类会执行 我们经常会写一个处理文件的main方法,使用时再去寻找,入入会比较麻烦,这里就可以把我们写过的main方法打成jar包,放到指定的目录来处理文件并生成想要的结果 1.写出我们自己的main方法,本地…

C语言.自定义类型:结构体

自定义类型&#xff1a;结构体 1.结构体类型的声明1.1结构体回顾1.1.1结构体的声明1.1.2结构体变量的创建和初始化 1.2结构体的特殊声明1.3结构体的自引用 2.结构体内存对齐2.1对齐规则2.2为什么存在内存对齐2.3修改默认对齐数 3.结构体传参4.结构体实现位段4.1什么是位段4.2位…

深入浅出DBus-C++:Linux下的高效IPC通信

目录标题 1. DBus简介2. DBus-C的优势3. 安装DBus-C4. 使用DBus-C初始化和连接到DBus定义接口和方法发送和接收信号 5. dbus-cpp 0.9.0 的安装6. 创建一个 DBus 服务7. 客户端的实现8. 编译和运行你的应用9. 瑞芯微&#xff08;Rockchip&#xff09;的 Linux 系统通常会自带 db…

OpenLayers入门①(引入的是一个高德地图)

OpenLayers入门&#xff08;一&#xff09; - 知乎 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&qu…

使用RTSP将笔记本摄像头的视频流推到开发板

一、在Windows端安装ffmpeg 1. 下载ffmpeg:下载ffmpeg 解压ffmpeg-master-latest-win64-gpl.zip bin 目录下是 dll 动态库 , 以及 可执行文件 ;将 3 33 个可执行文件拷贝到 " C:\Windows " 目录下 ,将所有的 " .dll " 动态库拷贝到 " C:\Windows\Sy…

期权交割对股市是好是坏?2024期权交割日一览表

期权交割是指期权买方在期权合约到期日或之前行使期权&#xff0c;卖方履行义务&#xff0c;按照约定的价格和数量与期权卖方进行标的物的买卖或现金结算的过程。 交割方式 期权交割可以分为实物交割和现金交割&#xff0c;具体取决于合约规定。 实物交割 实物交割是指期权买…

【深度学习基础(1)】什么是深度学习,深度学习与机器学习的区别、深度学习基本原理,深度学习的进展和未来

文章目录 一. 深度学习概念二. 深度学习与机器学习的区别三. 理解深度学习的工作原理1. 每层的转换进行权重参数化2. 怎么衡量神经网络的质量3. 怎么减小损失值 四. 深度学习已取得的进展五. 人工智能的未来 - 不要太过焦虑跟不上 一. 深度学习概念 先放一张图来理解下人工智能…

Vue阶段练习:初始化渲染、获取焦点

阶段练习主要承接Vue 生命周期-CSDN博客 &#xff0c;学习完该部分内容后&#xff0c;进行自我检测&#xff0c;每个练习主要分为效果显示、需求分析、静态代码、完整代码、总结 四个部分&#xff0c;效果显示和准备代码已给出&#xff0c;我们需要完成“完整代码”部分。 练习…

MySQL__三大日志

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a;Redis__三大日志 ⏱️ 创作时间&#xff1a;2024年04月30日 ———————————————— 对于MySQL来说, 有…

Gateway Predicate断言(谓词)

是什么 Spring Cloud Gateway匹配路由作为Spring WebFlux HandlerMapping基础设施的一部分。 Spring Cloud Gateway包含许多内置的路由谓词工厂。 所有这些谓词都匹配HTTP请求的不同属性。 您可以使用逻辑 and 语句来联合收割机组合多个路由谓词工厂。 Predicate就是为了实现一…

基于EBAZ4205矿板的图像处理:03使用VIO调试输出HDMI视频图像

基于EBAZ4205矿板的图像处理&#xff1a;03使用VIO调试输出HDMI视频图像 在zynq调试时VIO是真的方便&#xff0c;特此写一篇博客记录一下 先看效果 项目简介 下面是我的BD设计&#xff0c;vtc用于生成时序&#xff0c;注意&#xff0c;2021.2的vivado的vtcIP是v6.2版本&…

Stm32CubeMX 为 stm32mp135d 添加 adc

Stm32CubeMX 为 stm32mp135d 添加 adc 一、启用设备1. adc 设备添加2. adc 引脚配置2. adc 时钟配置 二、 生成代码1. optee 配置 adc 时钟和安全验证2. linux adc 设备 dts 配置 bringup 可参考&#xff1a; Stm32CubeMX 生成设备树 一、启用设备 1. adc 设备添加 启用adc设…

JAVA前端快速入门基础_javascript入门(03)

写在前面:本文用于快速学会简易的JS&#xff0c;仅做扫盲和参考作用 本章节主要介绍JS的事件监听 1.什么是事件监听 事件:是指发生在HTML端的事件&#xff0c;主要指以下几种。 1.按钮被点击 2.鼠标移动到元素上 3.按到了键盘 事件监听:当触发了事件时&#xff0c;JS会执行相…

vue3、element-plus递归实现动态菜单

vue3、element-plus递归实现动态菜单 使用场景&#xff1a;动态菜单为什么使用递归递归在动态菜单中的实现 使用场景&#xff1a;动态菜单 动态菜单是指菜单项的数量和层次结构可能是动态的&#xff0c;通常来自后端或用户输入。这些菜单的特征包括&#xff1a; 多层嵌套&…

【webrtc】MessageHandler 3: 基于线程的消息处理:以sctp测试为例

消息处理可以用于模拟发包处理G:\CDN\rtcCli\m98\src\net\dcsctp\socket\dcsctp_socket_network_test.cc 这个实现中,onMessage还是仅对了一种消息进行处理,就是接收则模式下,打印带宽。当然,可能程序有多个消息,分别在不同的onmessage中执行?SctpActor:以一个恒定的速率…

【大语言模型LLM】-基于ChatGPT搭建客服助手(1)

&#x1f525;博客主页&#xff1a;西瓜WiFi &#x1f3a5;系列专栏&#xff1a;《大语言模型》 很多非常有趣的模型&#xff0c;值得收藏&#xff0c;满足大家的收集癖&#xff01; 如果觉得有用&#xff0c;请三连&#x1f44d;⭐❤️&#xff0c;谢谢&#xff01; 长期不…

利用大型语言模型提升个性化推荐的异构知识融合方法

在推荐系统中&#xff0c;分析和挖掘用户行为是至关重要的&#xff0c;尤其是在美团外卖这样的平台上&#xff0c;用户行为表现出多样性&#xff0c;包括不同的行为主体&#xff08;如商家和产品&#xff09;、内容&#xff08;如曝光、点击和订单&#xff09;和场景&#xff0…

C++ 堆结构和堆排序(从顶到底/从底到顶的大顶堆)+ 优化

一、堆结构和堆排序 &#xff08;1&#xff09;heapInsert&#xff0c;向上调整大根堆 和 heapify&#xff0c;向下调整大根堆 // i位置的数&#xff0c;向上调整大根堆 // arr[i] x&#xff0c;x是新来的&#xff01;往上看&#xff0c;直到不比父亲大&#xff0c;或者来到0…