Bubble_Sort
算法介绍
冒泡排序是一种基于交换的排序算法,每次通过相邻数的不断比较将大的数沉到后面,在这一过程中小的数也会逐渐浮到前面,便是冒泡排序。
代码实现
首先需要完成单趟排序,冒泡排序的单趟排序就是遍历一遍,不断地如果后一个数比前面小则交换,负责把最大的数(第一次)沉到最后。
for (int i = 0; i < n - 1; ++i)
{
if (arr[i] > arr[i + 1])
{
swap(&arr[i], &arr[i + 1]); //swap函数省略
}
}
而每次都可以让一个数到达尾部正确的位置,这就意味着,每次从头开始可以少走一次,故:
void bubble_sort(int* arr, int n)
{
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < n - 1 - i; ++j)
{
if (arr[j] > arr[j + 1])
{
swap(&arr[j], &arr[j + 1]);
}
}
}
}
若数组已经有序了,可知此时再比较已无意义,故可以增加一个变量判断是否有序,具体做法是检测是否进行了交换,如果一整个内循环下来没有进行交换则排序已经完成,无需再大费周章做无用功,故可进行这样的优化:
void bubble_sort(int* arr, int n)
{
for (int i = 0; i < n - 1; ++i)
{
int is_sorted = 1;
for (int j = 0; j < n - 1 - i; ++j)
{
if (arr[j] > arr[j + 1])
{
swap(&arr[j], &arr[j + 1]);
is_sorted = 0;
}
}
if (is_sorted == 1) { break; } //已经有序则跳出
}
}
(我不推崇冒泡的双向排序,认为这是一种无意义的过程,减少大循环的次数但一次循环内需要完成两次 for 循环,本质效率没有提升)
效率分析
冒泡排序时间复杂度:O(N^2)
第一次排序:进行了 n - 1 次比较。
第二次排序:进行了 n - 2 次比较。(因为最大的数已经被放到最后)
第三次排序:进行了 n - 3 次比较。
......
倒数第二次比较:进行了 2 次比较。
最后一次比较:进行了 1 次比较。
故:(n - 1) + (n - 2) + (n - 3) + ...... + 2 + 1 == n * (n - 1) / 2 == 1/2 * (n^2 - n)
忽略常数项和低次项,故时间复杂度为:O(N^2)
补充说明
- 冒泡排序是稳定的排序算法,因为存在相同数据时依然能保证相同的数据不会交换相对位置,因为它并不可能被交换到另一个相同数据的位置之前或之后,因为它不比它们大或者小。