冒泡排序的分析以及优化
2015-04-28 13:05
260 查看
以前学习C语言的时候接触过两种最简单的排序方法,一个是冒泡排序法,另外一个是选择排序法。(我认为凡是学习过编程的人都会接触过!
我在这里阐述一下自己的理解:
1、时间复杂度:两个算法在最坏的情况下的冒泡排序时间复杂度用大O表示是O(N^2),而选择排序最坏情况是O(N) 在这点上也许看不出冒泡排序比选择排序要好;
2、**稳定性:从这个角度上来讲,冒泡排序的稳定性是要比选择排序要高的,原因是冒泡排序在交换的过程中仅仅是两个元素之间进行比较交换,不会破坏相同元素的原有顺序,但是选择排序就不一样。这个不详细说明。
我看过在网上有许多人讨论冒泡与选择到底那个要好,争论不休,我认为没有必要,因为我觉得不同的算法都是要基于数据结构上来讲的,现有数据结构而后才有相对适应的算法,不可能两者调转过来。我们今天讨论的的冒泡排序的优化也能够很大程度的减少时间复杂度。而且稳定性也相对高。何乐不为呢?
下面来回顾一下冒泡的最经典形式:
在这里就不做过于简单的分析了。我说两点可以优化的地方:一个是运行时效率一个是减少时间复杂度,对于这两者我们需要引入两个知识点一个是位运算另一个是状态机的思想。
第一点:位运算改善运行效率
对于编程有一定理解的人都会知道下面这一段代码:
设 a = 1, b = 2;若不想使用第三个变量来使得a 和 b进行交换那么我们就可以用到位运算!
实现为:a = a ^ b; => a ^= b;
b = b ^ a; => b ^= a;
a = a ^ b; =>
a ^= b;
注:前面为全写的表达式,后面是复合表达式。
了解过计算机底层的朋友都一定知道,位运算要比变量之间的运算(加减乘除相互赋值)要快的许多!这段代码能够很大程度的改善运行时效率。就如同以前跑1000米是4分钟。现在经过优化只需要3分钟了。
第二点:状态机思想改善时间复杂度(减少不必要的循环次数)
冒泡排序法就是无论任何情况,都是需要排序(N^2)次。无可避免,那么我们能否想一个办法来使得它能尽最大能力的去减少循环的次数呢?那就要借用我们状态机的思想:
具体思路是这样:①程序一开始设置一个状态变量state = -1
②当如果有元素需要比较时我们就可以让state = 1;
③如果经过了一轮比较下来,我们的状态变量state 还是为 -1 的话我们就可以判定为目标数组已经排好序!就可以结束程序,
这样就能很大程度的减少不必要的循环次数!
经过位运算与状态机的优化的冒泡排序法的代码段如下:
观点如果有瑕疵希望大家给予纠正!感谢大家的帮助!
今天我想就冒泡排序法发表一下个人的观点。也许有人问为什么只讨论冒泡而不讨论选择排序?
我在这里阐述一下自己的理解:
1、时间复杂度:两个算法在最坏的情况下的冒泡排序时间复杂度用大O表示是O(N^2),而选择排序最坏情况是O(N) 在这点上也许看不出冒泡排序比选择排序要好;
2、**稳定性:从这个角度上来讲,冒泡排序的稳定性是要比选择排序要高的,原因是冒泡排序在交换的过程中仅仅是两个元素之间进行比较交换,不会破坏相同元素的原有顺序,但是选择排序就不一样。这个不详细说明。
我看过在网上有许多人讨论冒泡与选择到底那个要好,争论不休,我认为没有必要,因为我觉得不同的算法都是要基于数据结构上来讲的,现有数据结构而后才有相对适应的算法,不可能两者调转过来。我们今天讨论的的冒泡排序的优化也能够很大程度的减少时间复杂度。而且稳定性也相对高。何乐不为呢?
下面来回顾一下冒泡的最经典形式:
//程序演示只以5为例 #define N 5 int main(void) { int array = {5,4,3,2,1}; int i = 0,j = 0; int temp = 0; for(i = 0;i < N-1; i++) { for(j = 0;j < N-i-1;j++) { if(array[j] > array[j+1]) { temp = array[j+1]; array[j+1] = array[j]; array[j] = temp; } } } }
在这里就不做过于简单的分析了。我说两点可以优化的地方:一个是运行时效率一个是减少时间复杂度,对于这两者我们需要引入两个知识点一个是位运算另一个是状态机的思想。
第一点:位运算改善运行效率
对于编程有一定理解的人都会知道下面这一段代码:
设 a = 1, b = 2;若不想使用第三个变量来使得a 和 b进行交换那么我们就可以用到位运算!
实现为:a = a ^ b; => a ^= b;
b = b ^ a; => b ^= a;
a = a ^ b; =>
a ^= b;
注:前面为全写的表达式,后面是复合表达式。
了解过计算机底层的朋友都一定知道,位运算要比变量之间的运算(加减乘除相互赋值)要快的许多!这段代码能够很大程度的改善运行时效率。就如同以前跑1000米是4分钟。现在经过优化只需要3分钟了。
第二点:状态机思想改善时间复杂度(减少不必要的循环次数)
冒泡排序法就是无论任何情况,都是需要排序(N^2)次。无可避免,那么我们能否想一个办法来使得它能尽最大能力的去减少循环的次数呢?那就要借用我们状态机的思想:
具体思路是这样:①程序一开始设置一个状态变量state = -1
②当如果有元素需要比较时我们就可以让state = 1;
③如果经过了一轮比较下来,我们的状态变量state 还是为 -1 的话我们就可以判定为目标数组已经排好序!就可以结束程序,
这样就能很大程度的减少不必要的循环次数!
经过位运算与状态机的优化的冒泡排序法的代码段如下:
int main(void) { <span style="white-space:pre"> </span>int array = {5,4,3,2,1}; <span style="white-space:pre"> </span>int i = 0,j = 0; <span style="white-space:pre"> </span>int state = -1;//定义状态 <span style="white-space:pre"> </span>for(i = 0;i < N-1; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>status = -1;// 每次进行大循环都定义为初始状态 <span style="white-space:pre"> </span>for(j = 0;j < N-i-1;j++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(array[j] > array[j+1]) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>state = 1;//一旦需要比较就改变状态 <span style="white-space:pre"> </span>array[j] ^= array[j+1]; <span style="white-space:pre"> </span>array[j+1] ^= array[j]; <span style="white-space:pre"> </span>array[j] ^= array[j+1]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if(state == -1) break;//如果执行过了一次大循环后状//态还是为初始状态那么就代表数组已经按预定的方式排好了序 <span style="white-space:pre"> </span>} }
观点如果有瑕疵希望大家给予纠正!感谢大家的帮助!
相关文章推荐
- java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序
- ios之经典算法冒泡排序以及优化
- 网页设计师须知的SEO技巧分析以及网站整体的优化规则
- Java实现冒泡排序以及优化冒泡排序的一些小技巧
- ViewFlipper源码分析以及通过view复用优化viewFlipper用法
- 回首Java——八大排序以及冒泡排序,插入排序分析实现
- CleanCSS — CSS分析以及优化利器[转]
- C++拷贝构造函数、无名临时对象以及NRV优化分析
- 13 算法/分析方法的优化以及总结
- 优化案例1---用分析函数优化优化执行计划中的FILTER以及标量子查询
- 冒泡排序的Java实现、性能分析以及适用场景
- 数据结构 — 冒泡排序以及其优化
- Android 性能优化之优秀工具以及分析
- Mustache php 版开源项目 流程 性能分析 以及优化
- mysql优化Analyze Table 以及批量分析表的命令
- Dijkstra's Algorithm分析以及其优化
- 快速排序的复杂度分析以及使用插入排序优化的快速排序
- *冒泡排序及其算法优化分析
- php 冒泡排序的两种思路以及优化
- 阿里云大数据MaxCompute计算资源分布以及LogView分析优化