算法原理:
设待排数据元素序列的元素个数为n,
1. 从后向前,比较相邻两个元素,若前一个元素比后一个元素大,则交换二者;
2. 对每一对相邻元素做以上的动作,直到最前面的一对比较完成后,最小的元素被交换至第一个位置;
3. 对剩下的n-1个元素重复以上的两个动作,每趟完成后,下一趟需要排序的元素就会减少1个,直至最后的两个元素不需要交换为止。
最终得到原序列从小到大排序的序列
算法稳定性
冒泡排序其实就是在每趟循环中将最小的元素往前移动(或者最大的元素往后移动),循环中比较相邻的两个元素,若不相等则可能会有交换动作,相等的时候不会做交换,大小相等的元素顺序没有改变,所以冒泡排序是一种稳定排序。
算法复杂度
冒泡排序最好的时间复杂度为O(n),即已经排好顺序的序列,只需要比较n-1次就完成排序
冒泡排序最坏的时间复杂度为O(
n2),即完全逆序的序列
代码实现
将5,1,3,8,2,9,6这个序列用冒泡排序从小到大排序
#include <stdio.h>
#include <stdlib.h>
//将数组中元素打印出来
void PrintNum(int* a, int length)
{
int i = 0;
for( i = 0; i < length; i++ )
{
printf("%d ", a[i]);
}
printf("\n");
}
//交换数组中两个数据的位置
void Swap(int* a, int i, int j)
{
int b = a[i];
a[i] = a[j];
a[j] = b;
}
int main(int argc, char *argv[])
{
int array[7] = {5, 1, 3, 8, 2, 9, 6};
int i = 0;
int j = 0;
int length = sizeof(array)/sizeof(*array);
int exchange = 0;
int flag = 0; //记录实际有交换的趟数
PrintNum(array, length); //打印排序之前的序列
for( i = 0; i < length; i++ )
{
if(1 == exchange)
{
exchange = 0;
flag++;
}
for( j = length - 1; j > i; j-- )
{
//如果前一个元素比后一个大,则交换
if( array[j-1] > array[j] )
{
Swap(array, j, j-1);
exchange = 1;
}
}
}
PrintNum(array, length); //打印排序之后的序列
printf("turns: %d\n",flag);
return 0;
}
运行结果:
可以看到实际有交换的趟数只有3趟,那么是不是可以对上面的程序最一点点改进呢,如果在某趟中没有进行过交换,说明已经按照我们想要的顺序排好了,那么可以直接退出循环,减少后续比较所消耗的时间提高效率。我们对上面的程序改进如下:
#include <stdio.h>
#include <stdlib.h>
//将数组中元素打印出来
void PrintNum(int* a, int length)
{
int i = 0;
for( i = 0; i < length; i++ )
{
printf("%d ", a[i]);
}
printf("\n");
}
//交换数组中两个数据的位置
void Swap(int* a, int i, int j)
{
int b = a[i];
a[i] = a[j];
a[j] = b;
}
int main(int argc, char *argv[])
{
int array[7] = {5, 1, 3, 8, 2, 9, 6};
int i = 0;
int j = 0;
int length = sizeof(array)/sizeof(*array);
int exchange = 1;
int flag = 0; //记录总的趟数
PrintNum(array, length); //打印排序之前的序列
for( i = 0; i < length && exchange; i++ )//当上一趟循环中有实际交换时才进入下一趟循环
{
exchange = 0; //如果本趟循环没有进行过交换,exchenge的值始终为0,下次将退出循环
flag++;
for( j = length - 1; j > i; j-- )
{
//如果前一个元素比后一个大,则交换
if( array[j-1] > array[j] )
{
Swap(array, j, j-1);
exchange = 1; //如果有实际交换,那么让标志位为1进行下一趟循环
}
}
}
PrintNum(array, length); //打印排序之后的序列
printf("turns: %d\n",flag);
return 0;
}
运行结果:一共循环了4趟;其中前3趟有交换动作,最后一趟没有交换动作,而没改进之前走了7趟。