算法设计优化——起泡排序

文章目录

  • 0.概述
  • 1 起泡排序(基础版)
    • 1.1 算法分析
    • 1.2 算法实现
    • 1.3 重复元素与稳定性
    • 1.4 复杂度分析
  • 2 起泡排序(改进版)
    • 2.1 目标
    • 2.2 改进思路
    • 2.3 实现
    • 2.4 复杂度分析
  • 3 起泡排序(改进版2)
    • 3.1 目标
    • 3.1 改进思路
    • 3.2 代码实现
  • 4 起泡排序(改进版3)
    • 4.1 目标
    • 4.2 改进思路
    • 4.3 实现

0.概述

介绍起泡排序算法的优化思路与实现。

1 起泡排序(基础版)

1.1 算法分析

在这里插入图片描述

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趟扫描交换

1.3 重复元素与稳定性

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

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

1.4 复杂度分析

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

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

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

故乱序元素仅限于 A[0, n \sqrt n n )区间,最坏情况下仍需调用 bubblesort ()做 Ω \Omega Ω( n \sqrt n n )次调用,共做 Ω \Omega Ω(n)次交换操作和 Ω \Omega Ω(n 3 2 ^{\frac 32} 23)次比较操作,因此累计运行 Ω \Omega Ω(n 3 2 ^{\frac 32} 23)时间。

2 起泡排序(改进版)

2.1 目标

乱序元素仅限于 A[0, n \sqrt n n )区间,仅需 O(n)时间。

2.2 改进思路

基础版问题:
所多余出来的时间消耗,无非是在后缀中对已就位元素的反复扫描交换,这些元素都是不必扫描交换的,可惜,基础版算法无法将其分解出来。

改进思路:
通过方法记录在上一趟扫描交换过程中所进行的最后一次交换,便可确定在上一趟扫描的区间中有一个多长的后缀实际上没有做过任何交换。如何可以,直接将hi指向新的位置。
在这里插入图片描述

2.3 实现

template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort ( Rank lo, Rank hi ) //assert: 0 <= lo < hi <= size
{ while ( lo < ( hi = bubble ( lo, hi ) ) ); } //逐趟做扫描交换,直至全序
template <typename T> 
Rank Vector<T>::bubble ( Rank lo, Rank hi ) { //一趟扫描交换Rank last = lo; //最右侧的逆序对初始化为[lo - 1, lo]while ( ++lo < hi ) //自左向右,逐一检查各对相邻元素if ( _elem[lo - 1] > _elem[lo] ) { //若逆序,则last = lo; //更新最右侧逆序对位置记录,并swap ( _elem[lo - 1], _elem[lo] ); //通过交换使局部有序}return last; //返回最右侧的逆序对位置
}

2.4 复杂度分析

这里将逻辑型标志sorted改为秩last,以记录各趟扫描交换所遇到的最后(最右)逆序元素。如此,在乱序元素仅限于A[0, n)区间时,仅需一趟扫描交换,即可将问题范围缩减至这一区间。累计耗时:
O(n + ( n ) 2 ( \sqrt n)^2 (n )2) = O(n)

3 起泡排序(改进版2)

3.1 目标

继续改进,使之在如下情况下仅需 O(n)时间:乱序元素仅限于 A[n - n \sqrt n n , n)区间;

3.1 改进思路

仿照改进版1)的思路与技巧,将扫描交换的方向调换为自后(右)向前(左),记录最前(最左)逆序元素。

3.2 代码实现

template <typename T> //向量的起泡排序
void Vector<T>::bubbleSort ( Rank lo, Rank hi ) //assert: 0 <= lo < hi <= size
{ while ((lo = bubble(lo, hi)) < hi); } //逐趟做扫描交换,直至全序
template <typename T> 
bool Vector<T>::bubble ( Rank lo, Rank hi ) { //一趟扫描交换Rank last = hi; //最右侧的逆序对初始化为[hi - 1, hi]while ( lo < --hi ) //自右向左,逐一检查各对相邻元素if ( _elem[hi - 1] > _elem[hi] ) { //若逆序,则last = hi; //更新最右侧逆序对位置记录,并swap ( _elem[hi - 1], _elem[hi] ); //通过交换使局部有序}return last; //返回最右侧的逆序对位置
}

4 起泡排序(改进版3)

4.1 目标

综合以上改进,使之在如下情况下仅需 O(n)时间:乱序元素仅限于任意的 A[m, m+ n \sqrt n n )区间。

4.2 改进思路

综合以上的思路与技巧,方向交替地执行扫描交换,同时动态地记录和更新最左和最右的逆序元素。

4.3 实现

#include <iostream>using namespace std;using Rank = int;//  自左向右,逐一检查各对相邻元素
Rank bubbleHi(Rank* A, Rank lo, Rank hi) { //一趟扫描交换int last = lo; //最右侧的逆序对初始化为[lo - 1, lo]while (++lo < hi) //自左向右,逐一检查各对相邻元素if (A[lo - 1] > A[lo]) { //若逆序,则last = lo; //更新最右侧逆序对位置记录,并swap(A[lo - 1], A[lo]); //通过交换使局部有序}return last; //返回最右侧的逆序对位置
}//自右向左,逐一检查各对相邻元素
Rank bubbleLo(Rank* A, Rank lo, Rank hi) { //一趟扫描交换int last = hi; //最右侧的逆序对初始化为[hi - 1, hi]while (lo < --hi) {//自右向左,逐一检查各对相邻元素if (A[hi - 1] > A[hi]) { //若逆序,则last = hi; //更新最右侧逆序对位置记录,并swap(A[hi - 1], A[hi]); //通过交换使局部有序}}return last; //返回最右侧的逆序对位置
}//向量的起泡排序
int bubbleSort(Rank* A, Rank lo, Rank hi) //assert: 0 <= lo < hi <= size
{int lo2 = bubbleLo(A, lo, hi);while (lo2 < (hi = bubbleHi(A, lo2, hi)));return 0;
} //逐趟做扫描交换,直至全序int main()
{//int a[19] = { 5,10,12,14,26,31,38,39,42,46,49,51,54,59,72,79,82,86,92 };//int a[19] = { 72,59,54,51,49,46,42,39,38,31,26,14,12,10,5,79,82,86,92 };int a[18] = { 5,10,12,14,26,31,38,39,54,51,49,46,42,59,72,82,86,92 };bubbleSort(a, 0, 18);int i;for (i = 0; i < 18; i++) { cout << a[i] << "  "; }cout << endl;return 0;
}

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

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

相关文章

edge 入门基础了解使用

随着Windows 11的发布&#xff0c;Microsoft Edge也迎来了新的更新和改进。作为一名长期使用Edge的用户&#xff0c;我不仅注意到了这些表面的变化&#xff0c;还深入研究了Edge在Windows 11上的新特性和潜在优势。 快捷方式 查找框 在Microsoft Edge浏览器中&#xff0c;按…

智能穿戴终端设备安卓主板方案_MTK平台智能手表PCBA定制开发

新移科技智能手表方案兼容WiFi、BLE、2~5G等多种通信能力。支持多个功能模块&#xff0c;包括&#xff1a;通话、计步、定位、睡眠监测、心率监测、血氧监测等。智能手表通过滑动与功能性按键提供高度直观的体验感受&#xff0c;从腕间即可掌控日常生活。形态支持定制包括&…

MySQL从入门到高级 --- 4.约束

文章目录 第四章&#xff1a;4.MySQL约束4.1 主键约束4.1.1 添加单列主键4.1.2 添加多列主键(联合主键)4.1.3 通过修改表结构添加主键4.1.4 删除主键约束4.1.5 自增长约束特点 4.1.6 指定自增字段初始值 - 创建表时指定4.1.7 指定自增字段初始值 - 创建表之后4.1.8 delete与tru…

洞察未来:数据治理中的数据架构新思维

随着大数据时代的来临&#xff0c;数据已经成为企业运营和社会发展的重要资产。然而&#xff0c;数据的复杂性和快速增长给企业带来了前所未有的挑战。在这样的背景下&#xff0c;数据治理成为了企业不可或缺的一环。数据治理不仅涉及数据的管理、安全和隐私保护&#xff0c;更…

ubuntu部署sonar与windows下使用sonar-scanner

ubuntu部署sonar与windows下使用sonar-scanner sonar部署java安装mysql安装配置sonarqube 插件安装sonar-scanner使用简单使用 sonar部署 使用的是sonarqube-7.5&#xff0c;支持的java环境是jdk8&#xff0c;且MySQL版本 >5.6 && <8.0 java安装 打开终端&…

Jackson-自定义注解及实现数据脱敏、枚举转换

Hi,大家好&#xff0c;我是抢老婆酸奶的小肥仔。 上一章&#xff0c;我们介绍了下Jackson及相关的注解&#xff0c;其实我们可以通过仿照一些注解来实现自定义以满足我们自己的业务需求&#xff0c;这一章&#xff0c;我们来说说jackson提供的自定义注解及一些应用吧。 废话不…

Virtualbox7.0.10--创建虚拟机

前言 下载Virtualbox7.0.10&#xff0c;可参考《Virtualbox–下载指定版本》 Virtualbox7.0.10具体安装步骤&#xff0c;可参考《Virtualbox7.0.10的安装步骤》 Virtualbox7.0.10创建虚拟机&#xff0c;可参考《Virtualbox7.0.10–创建虚拟机》 Virtualbox7.0.10安装Ubuntu20.0…

后端如何处理接口的重复调用

首先是&#xff0c;原理在请求接口之前&#xff0c;使用过滤器拦截数据&#xff0c;来进行判断两次数据是否一致。 1.自定义注解 2.创建一个Handler处理器 3.RepeatSubmitInterceptor的实现类 4.过滤器的配置

大型企业总分支多区域数据传输,效率为先还是安全为先?

大型企业为了业务拓展需要&#xff0c;会在全国乃至全球各地设立分公司和办事机构&#xff0c;以便更好地处理当地事务&#xff0c;并进行市场的开拓和客户维护&#xff0c;此时&#xff0c;企业内部就衍生出了新的业务需求&#xff0c;即多区域数据传输。 多区域很难准确定义&…

[C++][算法基础]最大不相交区间数量(贪心 + 区间问题2)

给定 &#x1d441; 个闭区间 [&#x1d44e;&#x1d456;,&#x1d44f;&#x1d456;]&#xff0c;请你在数轴上选择若干区间&#xff0c;使得选中的区间之间互不相交&#xff08;包括端点&#xff09;。 输出可选取区间的最大数量。 输入格式 第一行包含整数 &#x1d4…

Aiseesoft Data Recovery for Mac:专业数据恢复软件

Aiseesoft Data Recovery for Mac是一款高效且专业的数据恢复软件&#xff0c;专为Mac用户量身打造。 Aiseesoft Data Recovery for Mac v1.8.22激活版下载 无论是由于误删、格式化还是系统崩溃等原因导致的数据丢失&#xff0c;Aiseesoft都能帮助您快速找回。 它采用先进的扫描…

IDEA插件-通义灵码 VS ChatGPT-EasyCode

智能编码助手新时代&#xff1a;通义灵码 vs ChatGPT-EasyCode 随着人工智能技术的飞速发展&#xff0c;智能编码助手逐渐成为程序员的必备工具。它们可以帮助程序员提高编码效率&#xff0c;降低代码缺陷率&#xff0c;并解放创造力。 目前市场上涌现出了众多智能编码助手&a…

Golang | Leetcode Golang题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; func getPermutation(n int, k int) string {factorial : make([]int, n)factorial[0] 1for i : 1; i < n; i {factorial[i] factorial[i - 1] * i}k--ans : ""valid : make([]int, n 1)for i : 0; i < len(valid); i {…

【哈希】Leetcode 217. 存在重复元素

题目讲解 217. 存在重复元素 算法讲解 使用set集合完成元素的存储&#xff0c;当我们将当前元素插入到集合单中&#xff0c;如果insert的返回值的pair.second等于false说明当前元素已经存在&#xff0c;反之元素在集合中存在 class Solution { public:bool containsDuplica…

开放式耳机哪个牌子好?五大爆款机型大盘点

开放式耳机采用挂耳设计&#xff0c;体积小巧&#xff0c;携带方便&#xff0c;并且更加通风透气&#xff0c;避免了耳朵过热和出汗导致的问题&#xff1b;更轻的重量能有效减少长期佩戴对耳朵带来的压力&#xff0c;佩戴时舒适度直接爆表&#xff0c;在跑步、爬山、打球等户外…

ip ssl证书无限端口

IP SSL证书是由CA认证机构颁发的一种特殊数字证书。大部分SSL数字证书都需要用户使用域名进行申请&#xff0c;想要对公网IP地址加密实现https访问就需要申请IP SSL证书。IP SSL证书采用了强大的加密算法&#xff0c;可以有效地防止数据在传输过程中被窃取或篡改&#xff0c;具…

Copilot Workspace是GitHub对人工智能驱动的软件工程的诠释

软件开发的未来是人工智能驱动的集成开发环境吗&#xff1f;至少GitHub 是这样想的。 在今年初秋于旧金山举行的 GitHub Universe 年度大会之前&#xff0c;GitHub 发布了 Copilot Workspace&#xff0c;这是一种开发环境&#xff0c;利用 GitHub 所称的 “Copilot 驱动的代理…

Pytest自动化测试框架详解

今日之失&#xff0c;未必不为后日之得。大家好&#xff0c;刚才在翻看之前整理的一些关于自动化测试的文档&#xff0c;突然发现一个比较详细的关于pytest框架的介绍和使用文章&#xff0c;对于打算使用python进行自动化测试编写的小伙伴&#xff0c;还是很值得一看的&#xf…

深度学习之基于YOLOv5烟花燃放智能检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着科技的进步和人们对环保、安全意识的提高&#xff0c;传统的烟花燃放监管方式已逐渐不能满足现代…

RSA加密---java和node兼容版(可直接复制使用)

目录 背景 实现 一、node代码 1、引入依赖 2、生成公钥和私钥 3、生成工具类 二、java代码 背景 本来项目的后端是node&#xff0c;里面登录接口用的是后端生成RSA公钥和私钥&#xff0c;公钥给前端网页用来加密&#xff0c;node后端解密&#xff0c;一切很和谐&#x…