冒泡算法(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 ...
随机推荐
- WebLogic启动时报错
java.lang.ClassCastException: com.octetstring.vde.backend.BackendRoot cannot be cast to com.octetstr ...
- csv转json文件
今天因为需要帮一个同事的新闻内容录入为html, 每次手改不方便,所以就弄了个csv(excel)转json的c++程序,然后再利用ejs把它渲染成网页,打开渲染好的网页再保存(不能保存源文件,不然还 ...
- unity3d游戏开发(一)——圈圈叉叉
参考:http://game.ceeger.com/forum/read.php?tid=1719 ———————————————————开始————————————— 好吧,吹了那么多我们开始吧,先 ...
- 关于JAVA面向对象基础整理以及个人的理解(适合初学者阅读)
JAVA的基础语法等都跟C有很大的相似之处,所以这里就不多啰嗦了.直接从数组开始. 数组: 1.声明 int [] a; 在声明的过程中,并没有分配空间给数组.我们可以在声明的同时,用new来分配相应 ...
- linux环境下验证码不显示的几种情况
linux环境下验证码不显示的几种情况 gd库扩展没有安装. 查看phpinfo(),看看有没有安装gd库 yum安装gd库或者phpize安装 安装完成后记得重启php-fpm bom头的原因 在生 ...
- centos SSH配置详解
基本概念 linux自带的ssh为OpenSSH ssh协议提供两种用户认证方式 1. 基于口令的安全认证:使用用户名.密码的方式对登录用户进行认证 2. 基于密钥的安全认证:使用公钥和私钥对的方 ...
- ThinkPHP中视图模型详解.
很多TP的新手对于模型中的视图模型不甚了解,官方虽然有详细手册,但是对于初学者来说还是比较难以理解! 先简单说一下视图模型所能实现的功能,基本就是主表与副表之间各个字段的关联问题,实现多表关联查询,相 ...
- SDUT 1570 C 旅行(DFS)
点我看题目 题意 : 中文不详述. 思路 :就是DFS一下,只要到达终点条数就加1,然后再注意一下方向,因为我就是没注意方向WA了,只能向上向右走,x是行,所以向上是x-1,向右是y+1,因为我没弄好 ...
- POJ 3349 Snowflake Snow Snowflakes(哈希)
http://poj.org/problem?id=3349 题意 :分别给你n片雪花的六个角的长度,让你比较一下这n个雪花有没有相同的. 思路:一开始以为把每一个雪花的六个角的长度sort一下,然后 ...
- JSON对象与JSON数组
一个对象以"{"(左括号)开始,"}"(右括号)结束.每个"名称"后跟一个":"(冒号):""名称/ ...