冒泡排序(含图解)

本文深入解析冒泡排序算法,介绍其工作原理、实现步骤及代码示例,探讨时间复杂度和稳定性,适合初学者理解排序算法的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所谓冒泡排序,是一种简单的排序方法,这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。


实现原理及过程(含图解)

比如我们对 “8,9,1,3,5,2,7,6” 这组n个数据进行排序,首先我们先从第1个数开始,然后分别与其他几个数进行比较,如果遇到比其小的(大的)就交换,经过一轮循环后最大的数(或最小的数)就在最末端。


首先两个数进行比较,遇小交换,遇大保留大的,然后继续下去,第一轮交换后(如下图)
在这里插入图片描述

重复操作到n-1次,只是每次比较的数减少一个

每一次交换后结果:
在这里插入图片描述



代码:

(两重循环,外循环控制趟数,内循环控制每趟需要比较的个数)

#include <iostream>
using namespace std;
void BubbleSort(int a[],int n)
{
	int t;
	for(int i=0;i<n-1;i++)		//循环n-1次即可,因为最后一次只有一个数
	for(int j=0;j<n-i-1;j++)	//参与比较的数每次减少一个
	{
		if(a[j]>a[j+1])
		{
			t=a[j];
			a[j]=a[j+1];
			a[j+1]=t;
		}
	}
}
//下面为设置标记变量的做法,效率更高,如果事先已排好序或中途排好则会退出循环
//void BubbleSort(int a[],int n) 
//{
//	int t,flag,i=0;
//	do
//	{
//		flag=0;
//		for(int j=0;j<n-i-1;j++)
//		{
//			if(a[j]>a[j+1])
//			{
//				t=a[j];
//				a[j]=a[j+1];
//				a[j+1]=t;
//				flag=1;
//			}
//		}	
//		i++;
//	}while(flag&&i<n-1);
//	
//}
int main()
{
	int a[8]={8,9,1,3,5,2,7,6};
	BubbleSort(a,8);
	
	for(int i=0;i<8;i++)
	cout<<a[i]<<endl;
	return 0;
}


时间复杂度: O(n²)

在设置标记变量之后:

如果事先已经排好序(正序),则一趟扫描即可完成,总的比较次数为n-1次,交换为0次,也就是说冒泡排序在最好情况下的时间复杂度为O(n);

如果事先顺序为逆序,冒泡排序总的比较次数为n(n-1)/2,移动次数为3n(n-1)/2次,所以冒泡排序在最坏情况下的时间复杂度为O(n²);

所以,当原始序列杂乱无序时,冒泡排序的平均时间复杂度为O(n²)。


稳定性:
冒泡排序在排序过程中,元素两两交换时,相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

### 冒泡排序算法静态图解与步骤解析 冒泡排序是一种简单的交换类排序方法,其核心思想是比较相邻的两个元素,并按照指定顺序(升序或降序)调整它们的位置。通过多次遍历数组,较的元素会逐渐“浮”到数组的一端。 #### 冒泡排序的核心逻辑 冒泡排序的主要过程可以分为以下几个部分[^2]: 1. **外层循环控制轮次** 外层循环负责控制整个排序过程,每一轮都会将当前未排序部分的最值移动到最后位置。 2. **内层循环执行比较交换** 内层循环用于逐一遍历尚未完成的部分,每次比较相邻的两个元素。如果前一个元素于后一个元素,则交换两者的位置。 3. **优化机制** 如果某一轮中没有任何交换发生,则说明数组已经完全有序,可以直接结束排序操作。 以下是基于上述描述的一个具体例子以及对应的静态图解: --- #### 示例:对数组 `[5, 3, 8, 6, 2]` 进行冒泡排序 初始状态:`[5, 3, 8, 6, 2]` ##### 第一轮: - 比较 `5` `3` → 交换 → `[3, 5, 8, 6, 2]` - 比较 `5` `8` → 不交换 → `[3, 5, 8, 6, 2]` - 比较 `8` `6` → 交换 → `[3, 5, 6, 8, 2]` - 比较 `8` `2` → 交换 → `[3, 5, 6, 2, 8]` 第一轮结束后最值 `8` 已经被移到最后一位。 ##### 第二轮: - 比较 `3` `5` → 不交换 → `[3, 5, 6, 2, 8]` - 比较 `5` `6` → 不交换 → `[3, 5, 6, 2, 8]` - 比较 `6` `2` → 交换 → `[3, 5, 2, 6, 8]` 第二轮结束后第二值 `6` 被移到倒数第二个位置。 ##### 第三轮: - 比较 `3` `5` → 不交换 → `[3, 5, 2, 6, 8]` - 比较 `5` `2` → 交换 → `[3, 2, 5, 6, 8]` 第三轮结束后第三值 `5` 被正确放置。 ##### 第四轮: - 比较 `3` `2` → 交换 → `[2, 3, 5, 6, 8]` 第四轮完成后,数组已全部有序。 最终结果:`[2, 3, 5, 6, 8]` --- #### 图解表示 | 初始 | ![Initial State](https://example.com/image_initial_state.png)[^2] | |------|------------------------------------------------------------| | 第一轮 | ![First Pass](https://example.com/image_first_pass.png) | | 第二轮 | ![Second Pass](https://example.com/image_second_pass.png) | | 第三轮 | ![Third Pass](https://example.com/image_third_pass.png) | | 第四轮 | ![Fourth Pass](https://example.com/image_fourth_pass.png) | 注意:以上链接仅为示意,请替换为实际可用的片资源。 --- #### Python 实现代码示例 ```python def bubble_sort(arr): n = len(arr) for i in range(n): # 控制轮次数 swapped = False # 添加标志位判断是否提前终止 for j in range(0, n-i-1): # 当前未排序部分 if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] swapped = True if not swapped: # 若本轮无任何交换则退 break return arr # 测试用例 array = [5, 3, 8, 6, 2] sorted_array = bubble_sort(array.copy()) print(sorted_array) # 输 [2, 3, 5, 6, 8] ``` --- #### 性能分析 - **时间复杂度** - 最坏情况 \( O(N^2) \),发生在逆序排列时。 - 最好情况 \( O(N) \),当输入已经是正序时可提前结束。 - **空间复杂度** 原地排序,仅需常量额外存储空间 \( O(1) \)。 --- #### § 1. 如何改进冒泡排序使其适应规模数据? 2. 冒泡排序与其他简单排序算法(如选择排序、插入排序)相比有哪些优缺点? 3. 是否可以用形化工具动态展示冒泡排序过程?如何实现? 4. 冒泡排序适合哪些特定场景下的应用? 5. 对于随机分布的数据集,哪种排序算法可能优于冒泡排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值