冒泡排序
来源:互联网 发布:如何设置javascript 编辑:程序博客网 时间:2024/05/22 11:44
概述
冒泡排序 (bubble_sort) 是计算机领域最经典的一种排序算法,它重复走访要排序的序列,每次比较相邻的两个元素,若次序错误就交换它们,直到整个序列有序。
由于冒泡排序每趟通过交换可以将最大(小)元素换至尾端,类似水中逐渐浮起的水泡,故以此得名。
原理
以排升序为例:
如上图所示,其排序步骤如下:
- 从前至后依次比较相邻元素,若它们的次序错误就交换其位置,直至比较到数组最后一个元素,此时完成一趟冒泡,且最大元素已经“冒”至尾端;
- 缩小排序范围,重复上述步骤,直至整个序列有序。
时间复杂度:
可以看到,对于 N 个元素的序列需要进行 N-1 趟冒泡,每趟都要遍历序列。在经过优化后,该算法最好的情况是对于有序序列只需遍历一趟,而最坏情况则是逆序需要遍历n趟,它的平均时间复杂度是:O(n^2)
在排序前后,key 值相同元素的相对位置不会发生变化,故该排序算法是稳定的
C语言实现
version 1.0
void BubbleSort(int *a, size_t n){ assert(a); for (size_t i = 0; i < n - 1; ++i){ for (size_t j = 1; j < n - i; ++j){ if (a[j-1] > a[j]){ //交换元素 int tmp = a[j-1]; a[j-1] = a[j]; a[j] = tmp; } } }}
上述代码虽然实现了冒泡排序,但是在处理有序序列时,它的时间复杂度还会是 O(n^2),我们期望的是:当序列有序时,我们就不必再排序。故在此基础上,我们增加一个标记变量,当发现某趟冒泡时,没有发生元素交换,那么说明整个序列已经有序,则无需再排。代码如下:
version 2.0
void BubbleSort(int *a, size_t n){ assert(a); bool flag = false;//标记是否有过交换 for (size_t i = 0; i < n - 1; ++i){ for (size_t j = 1; j < n - i; ++j){ if (a[j-1] > a[j]){ swap(a[j-1], a[j]); flag = true; } } if (!flag)//如果没交换过则已经有序,可以直接退出 break; }}
假如有一序列,它的后半段已经有序,只有前半段是无序的,那么我们每次就无序冒到最后一个元素才停止,所以,我们针对这种情况对 version 1.0
优化,增加一个标记,该标记用于记录每趟排序最后一个发生交换的位置,这样,在下次排序时,只需要排到上次最后一个发生交换的位置即可,这样就完美处理了上述的“后半段有序而前半段无序的情况了”。代码如下: version 3.0
void BubbleSort(int *a, size_t n){ assert(a); int lastSwap = n; int pos = lastSwap; while (lastSwap > 1){ pos = 0; for (size_t i = 1; i < lastSwap; ++i){ if (a[i - 1] > a[i]){ pos = i; swap(a[i - 1], a[i]); } } lastSwap = pos; }}
【作者:果冻 http://blog.csdn.net/jelly_9】
阅读全文
0 0
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 冒泡排序
- 功能
- Web项目中使用Spring 3.x + Quartz 2.x实现作业调度详解
- 面向对象--简单的内部类
- Ciclop开源3D扫描仪软件---Horus源码分析之src\horus\engine\calibration\Pattern.py
- Python中MySQLdb执行插入操作时
- 冒泡排序
- 短信监听器
- HTML5小游戏飞机大战
- SEI-CERT Java编程规范(Thread Apis)-不要调用Thread.run()
- linux终端通信write、wall、mesg
- IO流(6)--录入文件路径,拷贝此文件到当前项目
- iOS 自动检测版本更新APP
- LeetCode练习记录2017/12/10
- iOS 播放音频的几种方式