冒泡排序详解及优化

时间复杂度:最好O(n)         最坏(序列为逆序)O(n²)         平均O(n²)

空间复杂度:O(1)

稳定性:稳定

大部分人会写冒泡排序,概念也是笼统的听了一下并没有清晰的了解原理

这篇文章将讲解一下冒泡排序的各个值和范围的含义

首先看一下代码:

//冒泡排序基础版本
//i的含义:目前后面有序元素的数量
//[j < arr.size()-i-1] 的含义:比较到后面有序元素之前的元素
// -1是因为比如3个数需要比较两次,5个数需要比较四次
void bubbleSort(vector<int>& arr) {
	for (int i = 0; i < arr.size(); i++) {
		for (int j = 0; j < arr.size() - i-1; j++) {
			if (arr[j] > arr[j + 1]) {
				//交换
				arr[j] ^= arr[j + 1];
				arr[j+1] ^= arr[j];
				arr[j] ^= arr[j + 1];
			}
		}
	}
}

首先冒泡排序的核心思想就是: 将元素最大/小的依次放到最后面。

我们需要对所有元素进行排序没走一趟都会将最大/小值放在后面, 那么 i 在算法中的含义可以理解为后面有序元素的个数。

在内层循环比较中, 为什么比较的次数是 arr.size() - i-1 是因为:

首先 -i 是减去了后面有序元素的个数, 因为已经有序的元素就是已经确定了的, 不需要再次参与比较。

-1 是因为, 比如3个数需要比较两次,5个数需要比较四次, 那么 arr.size() - i 个元素就需要 arr.size() - i-1 次。

那么既然i代表后续有序元素的个数,那么是不是有序一定是一个一个放在后面的?

显然是不是的,那么我们怎么判断有序元素的范围,其实在冒泡排序中每次遇到不符合排序规则的元素就会发生交换,那么我们记录一下最后交换元素的位置,那他的后面就都是符合排序规则的有序元素。

void bubbleSort2(vector<int>& arr) {
	int flag;
	for (int i = 0; i < arr.size(); i++) {
		flag = 0;//标记最后一次交换的位置
		for (int j = 0; j < arr.size() - i - 1; j++) {
			if (arr[j] > arr[j + 1]) {
				//交换
				arr[j] ^= arr[j + 1];
				arr[j + 1] ^= arr[j];
				arr[j] ^= arr[j + 1];
				flag = j + 1;
			}
		}
		//flag == 0 表示发生0次交换即数组已经有序,退出
		if (flag == 0)break;
		//更新i(有序元素的个数)	-1是因为下一次循环会+1
		i = arr.size() - flag - 1;
	}
}

使用一个标记变量flag来标记最后一次交换的位置,每次走内循环设置flag=0,走完内层循环都更新一下 i 为 arr.size() - flag - 1 i 既然代表的是后续有序元素的数量,那么为什么还要-1?

因为循环结束会i++。

这样就对冒泡排序进行了优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值