一、冒泡排序的介绍及算法原理
冒泡排序又称交换排序法,是从观察水中气泡变化构思而来的,原理是从序列中的第一个元素开始,依次对相邻的两个元素进行比较,如果前一个元素大于后一个元素则交换它们的位置。如果前一个元素小于或等于后一个元素,则不交换它们;这一比较和交换的操作一直持续到最后一个还未排好序的元素为止。当这样的一趟操作完成时,序列中最大的未排序元素就被放置到了所有未排序的元素中最后的位置上,它就像水中的石块一样沉到了水底。而其它较小的元素则被移动到了序列的前面,就像水中的气泡冒到了水面一样。这就是为什么该算法被叫做冒泡排序的原因。
从以上对算法原理的图示讲解中,我们首先可以知道冒泡排序是一种交换排序,它需要进行大量的交换操作。其次,因为当两个元素相等时它们不会被交换,所以相等元素的相对位置在排序前后不会改变,因此冒泡排序又是一种稳定的排序算法。
通过堆算法的性能分析。一共要进行 n-1 趟,且第 i 趟需要比较 n-i 次,所以总共需要比较(n-1) + (n-2) + ... + 1 = n(n-1)/2次。
在最好的情况(序列中的元素已经排好序)下,总共需要交换0次;而在最坏的情况(序列中的元素为逆序时)下,每一次比较都要进行一次交换。因此总的元素移动次数为总的比较次数的3倍,即3n(n-1)/2;那么平均的元素移动次数为3n(n-1)/4。
因此,这第一版的冒泡排序的时间复杂度为O(n2);而空间复杂度为O(1),因为该算法只需要一个额外的变量用于交换元素。
二、冒泡排序程序示例
void bubbleSort(int data[], int len)
{
for(int i = len - 1; i >= 0; i--)
{
int flag = 0; // flag用来判断是否执行了数据交换的操作
for (int j = 0; j < i; j++)
{
if (data[j + 1] < data[j])
{
int tmp;
tmp = data[j];
data[j] = data[j + 1];
data[j + 1] = tmp;
flag++; // 如果执行过数据交换,则flag不为0
}
}
if (flag == 0)
break;
/*
当执行完一次扫描就判断是否执行过数据交换,如果没有执行过数据
交换,则表示此时数列已经是排好序的,不需要打印中间排序的结果。
*/
cout<<"过程数据:\t";
printData(data, len);
}
cout<<"最终数据:\t";
printData(data, len);
}
void printData(int data[], int len) // 使用循环打印数据
{
for (int i=0; i < len; i++) {
cout<<setw(5)<<data[i];
}
cout<<endl;
}
int main(void)
{
int data[8] = {12, 4, 8, 34, 66, 15, 65, 43}; //原始数据
int len = sizeof(data) / sizeof(data[0]);
cout<<"优化冒泡排序法\n原始数据:\t";
printData(data, len);
bubbleSort(data, len);
return 0;
}