排序算法之冒泡排序
什么叫冒泡?
由图片可以看出,冒泡就是泡泡之间相互交换位置,泡泡越大上升的越快,最终最大的泡泡变为第一个浮出水面
冒泡排序(Bubble Sort)一种交换排序,该排序算法的思想是:两两比较相邻记录的关键字(数值),如果反序则交换,直到没有反序的记录为止。
冒泡排序是排序算法中一般最先学习到的排序算法,但是在正式介绍排序算法前,先介绍一种像冒泡排序的排序算法。为什么说它像呢?我们先看代码再进行讨论。
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void Bubblesort(int* nums, int numsSize)
{
for (int i = 0; i < numsSize; i++)
{
for (int j = i + 1; j < numsSize; j++)
{
if (nums[i] > nums[j])
{
swap(&nums[i], &nums[j]);
}
}
}
}
上述代码中并不符合冒泡排序的两两比较相邻的元素这一特性,只是将两个反序的元素互换位置。因此在此基础上可以做出改进。
下面是正宗的冒泡排序算法,码友们可以看看有啥改进的地方。
void Bubblesort0(int* nums, int numsSize)
{
for (int i = 0; i < numsSize; i++)
{
for (int j = numsSize-1; j > i; j--)
{
if (nums[j-1] > nums[j])
{
swap(&nums[j-1], &nums[j]);
}
}
}
}
可以看出,每次比较的元素都是相邻的元素,算法是由尾部开始比较,第一次循环将最小的元素放到数组头部。这是升序排序的代码。降序排序的代码仅仅将大于号换成小于号就可以了。
该算法第一次循环的过程如下图所示:
那么我们思考一下,假如我们要排序的序列是{2,1,3,4,5,6,7,8,9}。可以看出啊,我们只要变换一次1和2的位置即可。但是用上面的代码的话,他还是会在序列变成有序后继续进行比较的操作。这时为了避免不必要的资源浪费,需要对上述代码进行优化。
我这里采用的优化策略是增加标志;我们知道的是,如果序列变得有序后,冒泡排序在一次循环中是不会交换元素位置的。因此我们可以将有无交换元素位置作为一个标志。具体代码如下:
void Bubblesort1(int* nums, int numsSize)
{
int count = 0;
static int flag = 1;
for (int i = 0; i < numsSize && flag; i++)
{
flag = 0;
for (int j = numsSize - 1; j > i; j--)
{
if (nums[j - 1] > nums[j])
{
swap(&nums[j - 1], &nums[j]);
flag = 1;
}
count++;
}
}
printf("count = %d\n", count);
}
优化前的代码比较次数是36次,优化后代码的比较次数是15次。
排序算法的时间复杂度的O(n2)。