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

news2024/11/23 0:20:50

文章目录

  • 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 <= n
	bool 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.coloradmin.cn/o/1633244.html

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

相关文章

鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班

本篇通过拆解一段很简单的汇编代码来快速认识汇编&#xff0c;为读懂鸿蒙汇编打基础.系列篇后续将逐个剖析鸿蒙的汇编文件. 汇编很简单 第一&#xff1a; 要认定汇编语言一定是简单的&#xff0c;没有高深的东西&#xff0c;无非就是数据的搬来搬去&#xff0c;运行时数据主要…

基于Spring Boot的体质测试数据分析及可视化系统设计与实现

基于Spring Boot的体质测试数据分析及可视化系统的设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 前台首页界面图&#xff0c;体质测试…

day17-day20_项目实战项目部署

万信金融 项目部署 目标&#xff1a; 理解DevOps概念 能够使用Docker Compose部署项目 理解持续集成的作用 会使用Jenkins进行持续集成 1 DevOps介绍 1.1 什么是DevOps DevOps是Development和Operations两个词的缩写&#xff0c;引用百度百科的定义&#xff1a; DevOps…

68.网络游戏逆向分析与漏洞攻防-利用数据包构建角色信息-自动生成CPP函数解决数据更新的问题

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

Seata-server配置

首先先兼容一下版本看看所用的版本是否都兼容 版本兼容查看 建立seata-server数据库 数据库DDL 给每个业务库建立undo.log表 undo.log 然后在虚拟机安装seata-server 创建文件路径&#xff0c;并创建docker-compose.yml文件 创建完成后先启动一下seata docker run -rm seata…

linux远程访问及控制

一、SSH远程管理 1.SSH的简介 SSH远程管理是一种通过 SSH 协议安全地管理远程计算机的方法。允许管理员通过加密的连接从本地计算机或其他远程位置连接到远程计算机&#xff0c;并执行管理任务、配置设置、故障排除等操作。 远程链接的两种方法&#xff1a;SSH 、Telnet S…

07_for循环返回值while循环

文章目录 1.循环返回值2.yield接收for返回值3.scala调用yield方法创建线程对象4.scala中的while循环5.scala中的流程控制 1.循环返回值 for循环返回值是Unit 原因是防止产生歧义&#xff1b; 2.yield接收for返回值 // 2.yield关键字打破循环&#xff0c;可以使for循环输出…

力扣HOT100 - 207. 课程表

解题思路&#xff1a; class Solution {public boolean canFinish(int numCourses, int[][] prerequisites) {int[] inDegree new int[numCourses];//存每个结点的入度List<List<Integer>> res new ArrayList<>();//存结点之间依赖关系Queue<Integer>…

Spring Security(学习笔记)--漏洞保护(csrf攻击与防御以及源码分析)!

重点标识 csrf 攻击防御演示&#xff01; 源码分析&#xff01; CSRF攻击与防御 CSRF是什么 &#xff0c;跨站请求伪造&#xff0c;简单解释一下&#xff0c;就是用户登录某个界面&#xff0c;如银行界面&#xff0c;进行转账&#xff0c;完了之后并没有注销登录&#xff0…

Scrapy 爬虫教程:从原理到实战

Scrapy 爬虫教程&#xff1a;从原理到实战 一、Scrapy框架简介 Scrapy是一个由Python开发的高效网络爬虫框架&#xff0c;用于从网站上抓取数据并提取结构化信息。它采用异步IO处理请求&#xff0c;能够同时发送多个请求&#xff0c;极大地提高了爬虫效率。 二、Scrapy运行原…

蒸镀的氧化硅薄膜为什么有时候是绿色有时候是棕色的?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;我们用热阻式蒸镀设备镀氧化硅薄膜&#xff0c;出来的颜色有时候会发生变化是什么原因呀&#xff1f;有时候薄膜是绿色有时候是棕色。 氧…

Excel 中用于在一个范围中查找特定的值,并返回同一行中指定列的值 顺序不一样 可以处理吗

一、需求 Excel 中&#xff0c;在一列&#xff08;某范围内&#xff09;查找另一列特定的值&#xff0c;并返回同一行中另一指定列的值&#xff0c; 查找列和返回列的顺序不一样 二、 实现 1、下面是一个使用 INDEX 和 MATCH 函数的例子&#xff1a; 假设你有以下数据&…

网络服务SSH-远程访问及控制

一.SSH远程管理 1.SSH介绍 SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;最早是由芬兰的一家公司开发出来&#xff0c;并且在IETF &#xff08;Internet Engineering Task Force&#xff09;的网络草案基础上制定而成的标准协议。主要用来实现字符…

深度学习pytorch实战-运动鞋识别P5周

向大佬学习大地之灯第P5周&#xff1a;Pytorch实现运动鞋识别http://t.csdnimg.cn/eVVAG >- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a…

MySQL8.0新特性

1、新增降序索引 MySQL 5.7&#xff1a;在语法上支持降序索引&#xff0c;但实际上创建的仍然是升序索引 MySQL 8.0&#xff1a;真正支持降序索引&#xff08;只有Innodb存储引擎支持降序索引&#xff09; # MySQL 5.7演示 mysql> create table t1(c1 int,c2 int,index i…

pytest教程-34-钩子函数-pytest_configure

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了pytest_addoption钩子函数的使用方法&#xff0c;本小节我们讲解一下pytest_configure钩子函数的使用方法。 pytest_configure(config) 是一个 pytest 钩子函数&#xff0c;它在 pytest 配置完…

资产管理软件价格 一套固定资产管理系统多少钱

固定资产管理系统作为一款帮助工厂、事业单位、政府机关等企业管理资产设备的管理工具&#xff0c;其实&#xff0c;一直在向企业提供着各种相关的服务&#xff0c;对于才接触固定资产管理系统的朋友们来说&#xff0c;首先想要了解的这个付费工具的收费问题&#xff0c;那这个…

关于谷歌浏览器对于https的证书不通过校验的无法跳转的问题

谷歌浏览器对于https的证书问题会出现如下提示: 解决方法: 直接在页面输入 thisisunsafe 就能跳转了.

精彩回顾|从 AI 到银幕:顶尖对话揭秘 AI 如何塑造影视新格局

4月17日&#xff0c;由万合天宜、三次元影业、NOVATECH、微软中国极客天团、微软 Reactor 共同推出的「从 AI 到银幕」顶尖对话在上海微软紫竹园区举办。中国内地著名导演、编剧、监制黄建新&#xff0c;微软&#xff08;中国&#xff09;有限公司首席技术官韦青&#xff0c;与…

孕线反转形态,Anzo Capital10年交易经验一眼看穿

很多投资者都知道Inside-bar孕线是一种很好的反转信号&#xff0c;但是不了解Inside-bar孕线如何一眼发现孕线反转形态&#xff0c;今天Anzo Capital昂首资本平台上的10年交易者进行免费分享&#xff0c;希望各位投资者能够一眼看穿孕线反转形态: 首先各位投资者发散一下思维&…