问题
用Bubble Sort对长度为n的无序序列s从小到大(升序)排序。
解法
将长度为n的序列s=[x0,x1,…,xn−1]分为左右两个部分,未排序的left=[x0,…,xk]和已排序的right=[xk+1,…,xn−1],其中0≤k≤n−1。如图:
初始时left=[x0,…,xn−1],right=∅。如图:
对left做如下操作:
function Bubble(s, k):
for i = [0, k]
if s[i] > s[i+1]
swap(s[i], s[i+1])
(1) Bubble函数第2行:从左向右遍历left中的所有元素s[i];
(2) Bubble函数第3-4行:比较s[i]和s[i+1],若s[i]>s[i+1]则交换两个元素,否则不做任何操作。这样一次操作会将left中的最大元素移动到最右边,下一次调用Bubble函数时,只需要将输入参数k变为k−1,就可以将上一次left最右边的元素加入right的最左边;
上述操作如图:
运行一次Bubble函数可以将left中最大的元素移动到right最左边(left长度减1,right长度加1)。初始时left长度为n,right长度为0,只需重复调用n次Bubble函数即可完成排序:
function BubbleSort(s, n):
for k = [n-1, 0]
Bubble(s, k)
例如对于下图中的数组s,left为s[0,5],right为s[6,n−1]。从i=0开始向右遍历,依次比较s[i]和s[i+1],若s[i]>s[i+1]则交换两个元素,直到i=5。
然后将left中的最大值s[5]=57合并到right部分中,再进行新一轮的遍历交换操作。
每次遍历都可以筛选出left中最大的元素,重复n次即可对整个数组完成排序,算法结束。
复杂度
Bubble函数的输入规模为T(k),遍历k个元素的时间复杂度为O(k),判断两个元素的大小、交换两元素的值的时间复杂度为O(1),该操作的时间复杂度为:
T(k)==O(k)+O(1)O(k) BubbleSort函数的输入规模为T(n),循环调用n次Bubble函数,时间复杂度为O(n),调用Bubble的平均输入规模为T(n),该操作的时间复杂度为:
T(n)==O(n)⋅O(n)O(n2) 该算法的时间复杂度为O(n2)。该算法没有额外占用内存(没有动态分配内存),空间复杂度为为O(1)。
源码
BubbleSort.h
BubbleSort.cpp
测试
BubbleSortTest.cpp