冒泡算法(C++模板实现)

时间:2021-11-08 06:14:05

冒泡排序

从整体上看,冒泡排序是一种稳定排序,即排序完成后,原本序列中的键值相等的元素相对位置不会发生改变。算法的时间复杂度是O(n2),空间复杂度为O(1),即这是一个“就地算法”。


简单的冒泡排序算法以及实现

冒泡算法的基本思想是先实现局部的有序性,再进一步实现整体的有序性。

从前向后依次检查每一对相邻元素,一旦发现逆序即交换二者的位置。对于长度为n的序列,共需做 n - 1次比较和不超过 n - 1次交换,这一过程称作一趟扫描交换。

举个例子,先来看看对于一个杂乱的序列{1, 3, 8, 2, 0, 5, 6, 4, 9, 7},如何排序成为一个升序呢?依据冒泡算法的基本思想,从前向后逐一对每一对相邻元素进行检查,若逆序则交换。

  1. 第1和2位,{1,3}顺序正确,看下一对
  2. 第2和3位,{3,8}顺序正确,看下一对
  3. 第3和4位,{8,2}顺序错误,进行交换,第3位变为2,第四位为8,即此时整体序列为{1, 3, 2, 8, 0, 5, 6, 4, 9, 7}
  4. {8,0}又是错序,进行交换,{1, 3, 2, 0, 8, 5, 6, 4, 9, 7}
  5. {1, 3, 2, 0, 5, 8, 6, 4, 9, 7}
  6. {1, 3, 2, 0, 5, 6, 8, 4, 9, 7}
  7. {1, 3, 2, 0, 5, 6, 4, 8, 9, 7}
  8. 注意,此时{8,9}这一局部的序列是符合升序的,所以看下一对
  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); // 输出显示数组的函数
}
}

运行结果如下图:

冒泡算法(C++模板实现)


冒泡算法改进

观察前面的结果,可以发现其实第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);
}
}

运行结果如下:

冒泡算法(C++模板实现)


双向冒泡算法(鸡尾酒算法)

传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,如果利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数大幅减少。

双向冒泡算法代码实现:

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);
}
}

运行结果:

冒泡算法(C++模板实现)


完整代码如下

#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++模板实现)的更多相关文章

  1. 1014 C语言文法定义与C程序的推导过程 程序:冒泡算法C程序(语法树)

    阅读并理解提供给大家的C语言文法文件. 参考该文件写出一个自己好理解版的现实版的完整版的C语言文法. 给出一段C程序,画出用上述文法产生这段C程序的完整语法树. 程序:冒泡算法C程序 点此文字查看原图 ...

  2. 冒泡算法C&num;

    冒泡算法C# namespace数组排序 { classProgram { staticvoidMain(string[]args) { inttemp=; ,,,,,,,,}; #region该段与 ...

  3. Python函数练习:冒泡算法&plus;快速排序(二分法)

    冒泡算法: #-*- coding: UTF-8 -*-#冒泡排序 def func(lt):if type(lt).__name__ !='list' and type(lt).__name__ ! ...

  4. javascript之冒泡算法

    今天看了js中数组的方法,其中sort()方法用于排序,就让我想到学C语言的时候有一个冒泡算法,就想用js写一个. <script> var arr=[1,30,20,40,21,31,1 ...

  5. php的冒泡算法

    <?php /* 冒泡算法  * @para $arr 传人进去排序的数组  * @return $newArr 排序之后的数组  */   function maopao($arr){     ...

  6. python学习之路-6 冒泡算法、递归、反射、os&sol;sys模块详解

    算法 冒泡算法 # 冒泡算法就是将需要排序的元素看作是一个个"气泡",最小的"气泡"最先浮出水面,排在最前面.从小到大依次排列. # 代码如下: li = [9 ...

  7. Python冒泡算法和修改配置文件

    先学习之前未完成的冒泡算法 li = [13,22,6,99,11] 从小到大 从第一个数字比较把大的往后移位 for m in range(4): num1 = li[m] num2 = li[m+ ...

  8. Python之collections序列迭代器下标式循环冒泡算法等

    练习题 元素分类 有如下值集合[11,22,33,44,55,66,77,88,99]将所有大于66的数作为一个列表放在字典的key为k1的value小于等于66的为k2的value {'k1':[7 ...

  9. Python系列之文件操作、冒泡算法、装饰器、及递归

    文件处理 python对文件进行读写操作的方法与具体步骤,包括打开文件.读取内容.写入文件.文件中的内容定位.及关闭文件释放资源等 open().file(),这个两函数提供了初始化输入\输出(I\O ...

随机推荐

  1. csharp&colon; Oracle Stored Procedure DAL using ODP&period;NET

    paging : http://www.codeproject.com/Articles/44858/Custom-Paging-GridView-in-ASP-NET-Oracle https:// ...

  2. Android Hack1 使用weight属性实现视图的居中显示

    本文地址:http://www.cnblogs.com/wuyudong/p/5898403.html,转载请注明源地址. 如果要实现如下图所示的将按钮居中显示,并且占据父视图的一半,无论屏幕是否旋转 ...

  3. 使用vue给导航栏添加链接

    如下面的导航栏,使用vue技术给该导航栏增加链接: js代码为: navigation:function(){ new Vue({ el: '#navUl', data: { menuData:{ ' ...

  4. Selenium for C&num;的入门Demo

    原文转载:http://www.cnblogs.com/halia/p/3562132.html?utm_source=tuicool 最近刚开始接触Selenium, 发现很多例子都是用java写的 ...

  5. 最小生成树Kruskal算法(邻接矩阵和邻接表)

    最小生成树,克鲁斯卡尔算法. 算法简述: 将每个顶点看成一个图. 在所有图中找权值最小的边.将这条边的两个图连成一个图, 重复上一步.直到只剩一个图. 注:将abcdef每个顶点看成一个图.将最小权值 ...

  6. iOS Foundation框架简介 -1&period;常用结构体的用法和输出

    1.安装Xcode工具后会自带开发中常用的框架,存放的地址路径是: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.plat ...

  7. chrome 插件 vimium 快捷键大全

    DESCRIPTION vimium是一款让你在chrome浏览器能方便地使用键盘操作浏览器的插件.虽然和firefox相比还有些许不足(比如不能按到一些按钮之类的),但是vimium还是做到了能在9 ...

  8. error2

         10:09:40 贾老师,请问这个错在哪里啊! ^^Li_Jia^^ 10:27:41 你第2个for的n是做什么的    10:28:06 换行 ^^Li_Jia^^ 10:28:26 这 ...

  9. java核心技术学习笔记之一程序设计概述

    Java 核心技术之一程序设计概述 一.   Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...

  10. Python学习笔记,day4

    Python学习第四天 一.装饰器 函数调用顺序: 其他高级语言类似,Python 不允许在函数未声明之前,对其进行引用或者调用 高阶函数: 满足下列条件之一就可成函数为高阶函数 某一函数当做参数传入 ...