周末闲着整理一下以前的资料,好记性不如烂笔头,也是个回顾的过程。
1.简述
冒泡排序呢,属于相邻元素比较的一种排序方法;
相邻元素根据大小换位置,从头换到尾,就逐渐把比较大的元素换到了后边。
2.原理呢
就是通过一轮轮的比较,在每一轮中获取这个数据中当前轮最大/小的元素,若前一个数大于/小于后一个数,则交换位置,如下:
第一轮比较:获取当前轮最大/小值,这个值也是咱们数据中的最大/小值;
第二轮比较:获取当前轮最大/小值,这个值是仅次于第一轮获取的数据;
。。。。
第n轮比较:获取的当前轮最大/小值,这个值也是容量为n的数据中最大/小的值了;
我自己的理解呢,就是可以把这些数据看作一团液体,每一轮的冒泡判断呢,就好比从这个液体中抠出去一部分,而要抠出去的是最大的一坨呢还是最小的一坨,这个无所谓,反正每一轮过后液体体积就减少了,从而下一轮我们要比较的次数也少了。
举个例子:数据{ 20, 40, 8, 96, 32, 12, 45, 67},容量n为8,按照升序排序:
第一轮:
要比较的是全部n个数据,这一轮就能获取到最大的值96,第一轮过后数据内容变为:
20,8,40,32,12,45,67,96 从而抠出来了最大的96;
第二轮:
需比较的元素个数减一(n-1),这一轮获取最大值次之元素,67,第二轮过后数据内容变为:
8,20,32,12,40,45,67,96 抠出来了67;
第三轮:
需比较元素个数再减一(n-2),获取到45,第三轮过后数据内容变为:
8,20,12,32,40,45,67,96 抠出来了45;
第四轮:
需比较元素个数再减一(n-3),获取到40,第四轮过后数据内容变为:
8,12,20,32,40,45,67,96 抠出来了40;
第五轮:
需比较元素个数再减一(n-4),获取到32,第五轮过后数据内容变为:
8,12,20,32,40,45,67,96 抠出来了32;
第六轮:
需比较元素个数再减一(n-5),获取到20,第六轮过后数据内容变为:
8,12,20,32,40,45,67,96 抠出来了20;
第七轮:
需比较元素个数再减一(n-6),获取到12,第七轮过后数据内容变为:
8,12,20,32,40,45,67,96 抠出来了12;
第八轮:
需比较元素个数再减一(n-7),获取到8,第八轮过后数据内容变为:
8,12,20,32,40,45,67,96 抠出来了8;
可以看到,比较轮数与元素总个数相同,每一轮比较的元素个数减少一个,并获取了当前剩余的数据中最大的那个值。
有两点需要注意的是:
(1)下一轮需要比较的元素个数,是总数减去已经抠出来的元素后剩下的;
(2)有n个数进行相邻元素互相比较时,只需要比较n-1次就可以;
稳定性:
稳定性是指数据中若干值相同的元素的相对位置,是否变化;
在冒泡判断过程中,若在小于/大于时才进行换位的情况下,是稳定的;
若小于等于/大于等于时候也进行换位的话,是不稳定的。
3.代码
void bubbleSort(int *array, int size)
{
if (NULL == array)
{
printf("array is NULL.\n");
return;
}
// loopNum表示需要比较的轮数,与元素总数相同
for (int loopNum = 0; loopNum < size; loopNum++)
{
// 判断条件要注意,每一轮比较时,剩余要比较的元素个数x:x = n-已抠出元素数
// 而x个元素相邻比较只需要判断x-1次即可,所以需要设置为如下形式
for (int cmpInLoop = 0; cmpInLoop < size - loopNum - 1; cmpInLoop++)
{
// 相邻元素左右之间比较
if (*(array + cmpInLoop) > *(array + cmpInLoop + 1))
{
int tmp = *(array + cmpInLoop + 1);
*(array + cmpInLoop + 1) = *(array + cmpInLoop);
*(array + cmpInLoop) = tmp;
}
}
}
}
4总结
(1)实现之前一定要知道其原理,并有自己的理解才行;
(2)通过原理部分的比较步骤,可看到在已经有序的情况下冒泡排序还是要循环判断,并且多次重复判断,这是很大的缺点,所以时间复杂度为O(n^2);