您的位置:首页 > 编程语言 > C语言/C++

冒泡排序的分析以及优化

2015-04-28 13:05 260 查看
    以前学习C语言的时候接触过两种最简单的排序方法,一个是冒泡排序法,另外一个是选择排序法。(我认为凡是学习过编程的人都会接触过!

今天我想就冒泡排序法发表一下个人的观点。也许有人问为什么只讨论冒泡而不讨论选择排序?


我在这里阐述一下自己的理解:

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


观点如果有瑕疵希望大家给予纠正!感谢大家的帮助!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息