本文通过图文的形式来介绍冒泡排序基本原理以及如何改良排序来提升速度。所以从两个方面介绍:
1、冒泡排序
2、改进排序
冒泡排序
有一组数据如下,我们想按照从小到大进行排序
我们排序思路是从右往左依次比较如果左边大于右边,就交换左边和右边的顺序。比较完之后我们可以确保左边第一个为最小值。
原始序列:
4 | 5 | 1 | 9 | 3 |
步骤一:比较3和9,由于3<9 交换位置 结果如下:
4 | 5 | 1 | 3 | 9 |
步骤二:比较3和1,由于3>1 不交换位置 结果如下:
4 | 5 | 1 | 3 | 9 |
步骤三:比较5和1,由于1<5 交换位置 结果如下:
4 | 1 | 5 | 3 | 9 |
步骤四:比较1和4,由于1<4 交换位置 结果如下:
1 | 4 | 5 | 3 | 9 |
经过四步的比较,我们发现第一个已经变成了最小值。接下来我们把剩下的4个数字再按照上面的做法来一遍。
步骤一:比较9和3,由于9>3 不交换位置
1 | 4 | 5 | 3 | 9 |
步骤二:比较5和3,由于5>3 交换位置
1 | 4 | 3 | 5 | 9 |
步骤三:比较3和4,由于3<4 交换位置
1 | 3 | 4 | 5 | 9 |
步骤四:不需要进行比较,因为最开始的比较已经确保了左边第一个是最小值。
可以想象,我们最终比较的次数为:
4+3+2+1 = 10次
如果我们有N个数据的话,最后比较的次数我们用数学公式描述就是:
比较次数
我们会发现冒泡法比较的次数数量级随着N的增大,呈现平方级的变大。
改进排序
只要能够减少遍历的次数,我们就可以减少提高运行的速度。我们把原始数据分成两个组。原则上两边一样多,如果总数是奇数,就左边做一个。
4 | 5 | 1 | 9 | 3 |
我们先假设两边都按照从小到大排序。
1 | 4 | 5 | 3 | 9 |
步骤一:比较 1 和 3 ,由于1 < 3 此刻1为左右两边最小,将其丢入空队列
1 |
步骤二:比较 4 和 3 ,由于 4 > 3 此刻3为左右两边最小,将其丢入空队列
1 | 3 |
步骤三:比较4 和 9 ,由于4 < 9 此刻4为左右两边最小,将其丢入空队列
1 | 3 | 4 |
步骤四:比较5 和 9 ,由于5 < 9 此刻5为左右两边最小,将其丢入空队列
1 | 3 | 4 | 5 |
步骤五:将右边剩下的依次丢入队列 这里只剩下了9
1 | 3 | 4 | 5 | 9 |
这里我们一共比较了4次,操作了1次,合计5次。也就是说我们比较次数等于数的个数。
但是由于我们假设左右两边都按照从小到大已经排序好了。实际上,我们在这之前还需要将左右两边按照同样的步骤进行排序。
我们用一个树型图来表示一共计算的次数,整个比较分为4层,为了计算方便,最后一层不算进去。即总次数为5*3 = 15次。
假设有N个数的话,我们可以想象总次数为:
其中Log2N需要取整数部分。
按照公式计算:
当N=5,冒泡排序 10次 改良排序 15次
当N=8,冒泡排序 28次 改良排序 32次
当N=64,冒泡排序 2016次 改良排序 448次
当N=4096,冒泡排序 8386560次 改良排序53248次
由此可以发现,第二种方法在N越来越大的时候,性能提升会越来越好。