vlambda博客
学习文章列表

细说冒泡排序及其五种优化算法

“The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time.” - Tom Cargill 

译文:“最开始的90%的代码使用了程序员90%的时间,剩下的10%的代码也需要90%的开发时间。” - Tom Cargill


01

冒泡排序

     冒泡排序算法思想简单来说:在内层一次遍历中,arr[j] 与 arr[j - 1] 进行比较,如arr[j - 1] < arr[j], 不改变,反之互换值,保证arr[j]存储着 0~j - 1中的最大值,随一次遍历当前数组最大值也下沉至末尾,经过n - 1次外层循环,可使n - 1个元素下沉,最后一个元素位置确定,排序完成。
举个例子方便理解
例1:例如原数组为:0,34,66,12,100,98
进入第一次冒泡排序:
从下标1的元素(即34)排起:34与0比较,34大,数组仍为0,34,66,12,100,98
下标2的元素(即66):66与34比较,66大,数组仍为0,34,66,12,100,98
下标3的元素(即12):12与66比较,12小,互换位置,数组变换为0, 34,12,66,100,98
下标4的元素(即100):100与66比较,100大,数组仍为0,34,12,66, 100,98
下标5的元素(即98):98与100比较,98小,则互换位置,数组变换为0,34,12,66,98,100
查看规律, 排序过程中,下标 j的值在交换后,是0 ~ j - 1中最大的,利用的是不等号具有传递性;排序完成后,将100沉底,再进行新的循环时,只需排序0, 34, 12, 66, 98即可,最大值沉底。
具体实现代码如下:

02

冒泡排序优化

外层优化:即减少外层循环次数
     举例2:假设元素数组为1, 0, 2, 4,8,那么只需一次内层遍历即完成了,何须四次?可优化为在每次遍历中增加一个tag记录,如果发生交换,则将tag = false,循环结束检测是否tag发生变化,未发生变化一定是排序完成。
具体实现如下:
细说冒泡排序及其五种优化算法
内外层循环优化:即减少内层和外层循环次数
     如咱们的例1:在一次排序后数据变换为 0,34,12,66,98,100, 那么第二次内层遍历只需遍历0, 34, 12即可,无需遍历至 0, 34, 12, 66, 98 ,只需设置一个next记录最后交换位置,下一次循环就以next为终止。
具体实现如下:
细说冒泡排序及其五种优化算法
双向冒泡:一次下沉,一次上浮操作,来回交替
     举例3:1000,2,34,56,343,0,一次下沉和上浮操作排序完成。虽然没有优化循环次数,但大大减少交换次数。
具体实现如下:
细说冒泡排序及其五种优化算法
双向冒泡和外层优化一起配合使用
细说冒泡排序及其五种优化算法
双向冒泡和内外层优化配合使用
细说冒泡排序及其五种优化算法

03

冒泡优化效率对比

     现生成30万条数据使用以上冒泡排序+五种优化算法测试,测试结果如下:
细说冒泡排序及其五种优化算法
相信大家对结果有些疑惑,我猜测解答一下:
问:内外层皆优化算法为什么慢于原冒泡排序算法?
答:和初始数据有关,内外层皆优化中如果多次使用next记录,但最后一个数值仍需交换,白白浪费之前赋值时间,再加之逻辑判断,所以慢于原冒泡算法,但大部分情况下优于原算法。
问:优化外层为什么能比内外层皆优化速度还快?
答:因为在两者逻辑判断中boolean型比==快的多,用1亿条循环测试如下:
细说冒泡排序及其五种优化算法
问:优化算法的结果会发生改变吗?
答:会,因数据和数据量的不同会发生一定变化,特定条件下还可能产生相反的结果。即使采用统一数据,也可能因为对不同算法产生相反的影响。

欢迎关注“程序大世界”