冒泡算法(C++模板实现)
冒泡排序
从整体上看,冒泡排序是一种稳定排序,即排序完成后,原本序列中的键值相等的元素相对位置不会发生改变。算法的时间复杂度是O(n2),空间复杂度为O(1),即这是一个“就地算法”。
简单的冒泡排序算法以及实现
冒泡算法的基本思想是先实现局部的有序性,再进一步实现整体的有序性。
从前向后依次检查每一对相邻元素,一旦发现逆序即交换二者的位置。对于长度为n的序列,共需做 n - 1次比较和不超过 n - 1次交换,这一过程称作一趟扫描交换。
举个例子,先来看看对于一个杂乱的序列{1, 3, 8, 2, 0, 5, 6, 4, 9, 7},如何排序成为一个升序呢?依据冒泡算法的基本思想,从前向后逐一对每一对相邻元素进行检查,若逆序则交换。
- 第1和2位,{1,3}顺序正确,看下一对
- 第2和3位,{3,8}顺序正确,看下一对
- 第3和4位,{8,2}顺序错误,进行交换,第3位变为2,第四位为8,即此时整体序列为{1, 3,
2, 8
, 0, 5, 6, 4, 9, 7} - {8,0}又是错序,进行交换,{1, 3, 2,
0, 8
, 5, 6, 4, 9, 7} - {1, 3, 2, 0,
5, 8
, 6, 4, 9, 7} - {1, 3, 2, 0, 5,
6, 8
, 4, 9, 7} - {1, 3, 2, 0, 5, 6,
4, 8
, 9, 7} - 注意,此时{8,9}这一局部的序列是符合升序的,所以看下一对
- {9,7}是乱序的,进行交换。{1, 3, 2, 0, 5, 6, 4, 8,
7, 9
}
以上,就完成了一趟扫描交换。每一次比较,局部内的较大值会交换到后面,小的值会交换到前面,就像气泡在水中浮向水面,所以称为冒泡算法。注意一点,每进行过一趟扫描为排序中的最大值已经“沉入”最后,所以下一趟比较时,需要比对的数对会较少一,即n减一。
代码实现如下(C++):
// 对一个数组a使用冒泡算法进行升序排序
template <typename T>
void bubbleSort_simple(T a[], int n) {
// n为数组的规模大小
int count = n;
// count用于辅助输出显示第几趟扫描比较
while (n--) {
for (int i = 0; i < n; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
cout << "这是第" << count - n <<"趟比较: ";
printArray(a); // 输出显示数组的函数
}
}
运行结果如下图:

冒泡算法改进
观察前面的结果,可以发现其实第4趟比较后就已经达成目标了,然而原来程序中依然要等while (n--)
执行完,令n等于0才能结束,会浪费不少时间和系统资源。针对这一状况,可以设立一个标志位值。思想是这样的:当每次做一趟扫描,设最后发生过交换数值的位置为K,K的后面的位置的值已经是按序的了。下一趟排序就只用扫描到K位置之前的。若新的这一趟中的K值与上一轮相同,表明排序已经完成。
改进的冒泡算法代码实现如下:
template <typename T>
void bubbleSort_improved(T a[], int n) {
// n为数组的规模大小
int count = 0; // count用于记录第几趟扫描比较
int pos = n; // pos用于记录每一趟最后有发生交换的位置
int oldPos = 0; // 记录上一趟的最后有发生交换的位置,
// 与pos对比,若一样,说明已经排好序
while (n > 0 && n != oldPos) {
oldPos = n;
for (int i = 0; i < n; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
pos = i;
}
}
n = pos;
count++;
cout << "这是第" << count <<"趟比较后: ";
printArray(a);
}
}
运行结果如下:

双向冒泡算法(鸡尾酒算法)
传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,如果利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数大幅减少。
双向冒泡算法代码实现:
template <typename T>
void bubbleSort_bidirectional(T a[], int n) {
// n为数组的规模大小
cout << "双向冒泡排序实现。" << endl;
int count = 0;
int low = 0;
int high = n - 1;
while (low < high) {
for (int i = low; i < high; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
high--;
for (int j = high; j > low; j--) {
if (a[j] < a[j - 1]) {
T temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
low++;
count++;
cout << "第" << count <<"趟比较后: ";
printArray(a);
}
}
运行结果:

完整代码如下
#include <iostream>
using namespace std;
template <typename T>
void printArray(T a[]) {
int count = 10;
for (int i = 0; i < count; i++) {
cout << a[i] << " ";
}
cout << endl;
}
template <typename T>
void bubbleSort_simple(T a[], int n) {
// n为数组的规模大小
cout << "简单冒泡排序实现。" << endl;
int count = 0;
while (n--) {
for (int i = 0; i < n; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
count++;
cout << "第" << count <<"趟比较后: ";
printArray(a);
}
}
template <typename T>
void bubbleSort_improved(T a[], int n) {
// n为数组的规模大小
cout << "冒泡排序改进版实现。" << endl;
int count = 0; // count用于记录第几趟扫描比较
int pos = n; // pos用于记录每一趟最后有发生交换的位置
int oldPos = 0; // 记录上一趟的最后有发生交换的位置,
// 与pos对比,若一样,说明已经排好序
while (n > 0 && n != oldPos) {
oldPos = n;
for (int i = 0; i < n; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
pos = i;
}
}
n = pos;
count++;
cout << "第" << count <<"趟比较后: ";
printArray(a);
}
}
template <typename T>
void bubbleSort_bidirectional(T a[], int n) {
// n为数组的规模大小
cout << "双向冒泡排序实现。" << endl;
int count = 0;
int low = 0;
int high = n - 1;
while (low < high) {
for (int i = low; i < high; i++) {
if (a[i] > a[i + 1]) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
high--;
for (int j = high; j > low; j--) {
if (a[j] < a[j - 1]) {
T temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
low++;
count++;
cout << "第" << count <<"趟比较后: ";
printArray(a);
}
}
int main() {
int a[10] = {1, 3, 8, 2, 0, 5, 6, 4, 9, 7};
double b[10] = {4, 7.42, 8.309, 2.1, 6.34, 9.078, 3.098, 1.23, 5.27, 0.243};
int c[10] = {1, 3, 8, 2, 0, 5, 6, 4, 9, 7};
bubbleSort_simple(a, 10);
cout << endl;
bubbleSort_improved(b, 10);
cout << endl;
bubbleSort_bidirectional(c, 10);
cout << endl;
printArray(a);
printArray(b);
printArray(c);
return 0;
}
冒泡算法(C++模板实现)的更多相关文章
- 1014 C语言文法定义与C程序的推导过程 程序:冒泡算法C程序(语法树)
阅读并理解提供给大家的C语言文法文件. 参考该文件写出一个自己好理解版的现实版的完整版的C语言文法. 给出一段C程序,画出用上述文法产生这段C程序的完整语法树. 程序:冒泡算法C程序 点此文字查看原图 ...
- 冒泡算法C#
冒泡算法C# namespace数组排序 { classProgram { staticvoidMain(string[]args) { inttemp=; ,,,,,,,,}; #region该段与 ...
- Python函数练习:冒泡算法+快速排序(二分法)
冒泡算法: #-*- coding: UTF-8 -*-#冒泡排序 def func(lt):if type(lt).__name__ !='list' and type(lt).__name__ ! ...
- javascript之冒泡算法
今天看了js中数组的方法,其中sort()方法用于排序,就让我想到学C语言的时候有一个冒泡算法,就想用js写一个. <script> var arr=[1,30,20,40,21,31,1 ...
- php的冒泡算法
<?php /* 冒泡算法 * @para $arr 传人进去排序的数组 * @return $newArr 排序之后的数组 */ function maopao($arr){ ...
- python学习之路-6 冒泡算法、递归、反射、os/sys模块详解
算法 冒泡算法 # 冒泡算法就是将需要排序的元素看作是一个个"气泡",最小的"气泡"最先浮出水面,排在最前面.从小到大依次排列. # 代码如下: li = [9 ...
- Python冒泡算法和修改配置文件
先学习之前未完成的冒泡算法 li = [13,22,6,99,11] 从小到大 从第一个数字比较把大的往后移位 for m in range(4): num1 = li[m] num2 = li[m+ ...
- Python之collections序列迭代器下标式循环冒泡算法等
练习题 元素分类 有如下值集合[11,22,33,44,55,66,77,88,99]将所有大于66的数作为一个列表放在字典的key为k1的value小于等于66的为k2的value {'k1':[7 ...
- Python系列之文件操作、冒泡算法、装饰器、及递归
文件处理 python对文件进行读写操作的方法与具体步骤,包括打开文件.读取内容.写入文件.文件中的内容定位.及关闭文件释放资源等 open().file(),这个两函数提供了初始化输入\输出(I\O ...
随机推荐
- Java学习--Equals与“==”
在Java规范中,它对equals()方法的使用必须要遵循如下几个规则: equals 方法在非空对象引用上实现相等关系: 1.自反性:对于任何非空引用值 x,x.equals(x) 都应返回 tru ...
- OpenFileDialog组件打开文件....待续
1.常用属性 InitialDirectory 对话框的初始目录 this.openFileDialog1.InitialDirectory = "d:\\"; ...
- NSCharacterset
我们在nsstring的分割,查找等操作中,经常会提供两种函数,参数类型分别为NSString 和NSCharacterset,有什么不同呢? NSString 是有序字符串 NSCharacters ...
- 常用数据字典---bai
--常用数据字典 -- system: normal; sysdba --查询所有的逻辑对象.所有. select count(1) from dba_objects; select * from d ...
- iOS+JSPatch在线修改app功能-b
什么是热更新? 举个例子,你的app上架了,但是突然想添加个小功能,那么你有两种方法 第一种方法:在原生代码中修改源代码,然后提交到appStore,这个过程真是很漫长...虽然最近我提交的都是一两天 ...
- python 文件查找 glob
glob模块是最简单的模块之一,内容非常少.用它可以查找符合特定规则的文件路径名.跟使用windows下的文件搜索差不多.查找文件只用到三个匹配符:"*", "?&quo ...
- Hanoi
递归解决 汉诺塔 class Han{ int num; int steps; Han(int num){ this.num=num; } void total() { System.out.prin ...
- 自适应单本小说网站源码,基于bootstrap+dedecms。
具体效果:http://www.ishengxu.cc/ 基于bootstrap+dedecms,PC端与手机端自适应,广告位也都设计好了,很简单.
- Hyper-V中安装CentOS分辨率修改
Hyper-V还是极好用的,不过对linux的支持优点问题, 比如默认情况,linux分辨率被锁定了,这里有一个比较简单的方法修改,针对CentOS grubby --update-kernel=AL ...
- HDU 1166 敌兵布阵(线段树 单点更新)
点我看题目 题意 :HDU的中文题也不常见....这道题我就不详述了..... 思路 :这个题用线段树用树状数组都可以,用线段树的时候要注意输入那个地方,输入一个字符串的时候不要紧接着输入两个数字 ...