Bubble_Sort

160 阅读2分钟

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)


补充说明

  • 冒泡排序是稳定的排序算法,因为存在相同数据时依然能保证相同的数据不会交换相对位置,因为它并不可能被交换到另一个相同数据的位置之前或之后,因为它不比它们大或者小。