冒泡排序,顾名思义,就是想冒泡一样,较大的泡泡或者较小的泡泡会往某个方向移动,直到所有的泡泡有序为止。
一、简单排序实现
在给出正宗的冒泡排序之前,我们来看一种简单的冒泡排序(以升序为例)。假定一定一个无序序列,从第一个位置开始,将此位置的元素与后面所有无序的元素逐个进行比较,只要是比这个位置的元素值小的元素,就与这个位置的元素互换值,直到序列末尾。因此,我们可以确定这个位置的元素相较于剩余无序序列中是最小的,即,每一轮比较下来,我们都是能确定一个最小的元素。以下面的图为例:
原始无序序列如下,一共9个元素,下标从0——8:
进入迭代,第一轮,将下标为0的元素与之后的无序序列逐个进行比较,并将每次比较较小的元素存放在此。
可以知道后面的无序元素个数为8,因此需要比较8次才能确定最小元素。8次的结果如下:
1 < 9,互换
5 > 1,不变
8 > 1,不变
3 > 1,不变
7 > 1,不变
4 > 1,不变
6 > 1,不变
2 > 1,不变
好了,现在已经确定下标为0的位置的元素了,接下来确定下标为1的位置的元素。因为此下标之前的所有元素已经有序,因此只需要与后面的无序的
序列逐个进行比较得出最小元素。可知下标为1的后面有7个元素,因此需要比较7次才能得出最小值。7次比较结果如下:
5 < 9,互换
8 > 5,不变
3 < 5,互换
7 > 3,不变
4 > 3,不变
6 > 3,不变
2 < 3,互换
好了,经过第二轮,我们可以确定下标为1的位置的元素了。接下来第三轮将确定下标为2的位置元素了,依此类推,最后便能够使整个序列有序。
我们将这整个过程量化:假设序列的元素个数为n,那么我们将要逐个确认下标为0到n-1的位置的元素个数(当只剩最后一个元素的时候就不需要再比较了)。假设我们现在需要确认下标位置为i的位置的元素,将需要将下标为i的位置的元素逐个跟后面n-1-i个无序元素进行比较从而得到最小元素。这个过程需要两层循环便能完成,代码如下:
void BubbleSort0(int array[], int arrayCount)
{
for(int i = 0; i < arrayCount - 1; ++i) //下标从0到arrayCount-2,依次确定每个位置的元素
{
for(int j = i + 1; j < arrayCount; ++j) //每次都与i后面的无序序列比较,得到最小的元素存放在此
{
if(array[j] < array[i]) //如果发现比当前确定位置的元素要小,则互换,以保证当前确定位置总是存放最小元素
{
int temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
}
}
二、冒泡排序算法
6 > 2,2继续前浮4 > 2,2继续前浮7 > 2,2继续前浮3 > 2,2继续前浮8 > 2,2继续前浮5 > 3,2继续前浮1 < 2,1接棒前浮9 > 1,1继续前浮
好了,到达终点了,确定了下标为0的位置元素。下一轮将确定下标为1的位置元素,依然是最后一个元素开始“往上浮”,终点将变成下标为1的位置
。可以看出,这一轮不仅确定了一个元素位置,同时还将较小的2也往前移了,并且没有太大改变整个序列的顺序,这将是很稳定的排序。
我们将这个过程量化:每次确认一个,我们将依次确认下标为0到n-1的元素,最后一个元素无序再比较。假设我们将确定下标为i的位置元素,需要从
最后一个位置n-1上浮到位置i,依然是两次循环。代码如下:
void BubbleSort1(int array[], int arrayCount)
{
for(int i = 0; i < arrayCount - 1; ++i)
{
for(int j = arrayCount - 1; j > i; --j)
{
if(array[j] < array[j - 1]) //如果比当前浮动元素大,则互换一下
{
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
三、改进的冒泡排序
在准备进行第一轮冒泡的时候就已经是有序的序列了,因此第二轮的冒泡以及后面所有轮的冒泡都只是徒劳的比较,很浪费时间。因此我们在想,如
何能够让我们的冒泡排序算法能够感知到在某次冒泡后整个序列已经有序了呢?我们可以思考,对于有序序列来说,一次冒泡将不会发生任何的交换
;而对于无序的序列来说,一次冒泡肯定会发生交换;因此我们可以设置一个标识flag,初始化为0,0表示没有发生交换,1表示发生了交换。我们可
以在交换的代码段设置flag = 1,那么只要发生了一次交换,flag便为1了。然后我们可以在每轮的冒泡排序之前判断flag是否为0,如果为0则已经得
到有序序列了。代码如下:
void BubbleSort2(int array[], int arrayCount)
{
int flag = 1;
for(int i = 0; i < arrayCount - 1; ++i)
{
if(flag == 0) return;
for(int j = arrayCount - 1; j > i; --j)
{
flag = 0;
if(array[j] < array[j - 1]) //如果比当前浮动元素大,则互换一下
{
flag = 1;
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
代码如下:
const int MAXN = 50000;
int array[MAXN];
void main()
{
for(int i = 0; i < MAXN; ++i)
array[i] = rand() * rand();
clock_t ibegin = clock();
BubbleSort1(array, MAXN);
clock_t iend = clock();
cout<<"没有设置flag的时间为: "<<iend - ibegin<<" 毫秒\n";
ibegin = clock();
BubbleSort2(array, MAXN);
iend = clock();
cout<<"设置flag的时间为: "<<iend - ibegin<<" 毫秒\n";
system("pause");
}
运行结果如下: