冒泡排序是交换排序的一种。
官方定义:
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
原理:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。
- 每趟排序过后,最大的数就会沉底,不在参与后续的排序。
- 针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
复杂度:
-
时间复杂度:O(N^2)
相对于其他种类的排序,效率是比较低的。 -
空间复杂度:O(1)
稳定性:
稳定
示例图解:
7. 因为是两两比较,所以总的趟数比数组个数少1,也就是n-1;
8. 因为每趟排序过后,最大的数就会沉底(不再参与后续排序),那么后一趟排序要比较的次数就会比前一趟排序少1;
优化:
针对已经是有序的情况(相对冒泡排序中升序or降序而言)
例如:冒泡排序设置的是升序,而数组也已经是升序的情况
数组arr:1,2,3,4,5,6,7,8,9,10
那么第一轮排序是没有任何交换的。利用这一点,我们可以就做一些简要优化。
读者现在可能云里雾里,但不用急,结合下面代码示例,你很快就能明白我说的意思。
代码示例:
void Swap(int* a, int* b)
{
int tmp = 0;
tmp = *a;
*a = *b;
*b = tmp;
}
//升序版本
void BubbleSort(int a[],int sz)
{
//完成一轮过后,就有一个数被固定,所以下一轮要比较的次数就会减一
//交换在轮数
for (int i = sz - 1; i > 0; i--)
{
int flag = 0;
//优化已经是升序的情况
//每轮交换在次数
for (int j = 0; j < i; j++)
{
if (a[j] > a[j + 1])
{
Swap(&a[j], &a[j + 1]);
flag = 1;
}
}
if (flag == 0)
{
break;
}
}
}