32

漫画:什么是冒泡排序?

 5 years ago
source link: https://blog.csdn.net/csdnnews/article/details/81187659?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

RZvYbqn.gif

VJNjIzf.jpg!web

QfIRRjF.jpg!web

—————  当天上午  —————

QFNneuZ.jpg!web

ABjyYjA.jpg!web

aQzUzmQ.jpg!web

I3mYRfN.jpg!web

MZvMnu3.png!web

什么是冒泡排序?

冒泡排序的英文Bubble Sort,是一种最基础的交换排序。

大家一定都喝过汽水,汽水中常常有许多小小的气泡,哗啦哗啦飘到上面来。这是因为组成小气泡的二氧化碳比水要轻,所以小气泡可以一点一点向上浮动。

Ybiayeq.png!web

而我们的冒泡排序之所以叫做冒泡排序,正是因为这种排序算法的每一个元素都可以像小气泡一样,根据自身大小,一点一点向着数组的一侧移动。

具体如何来移动呢?让我们来看一个栗子:

MbYzIfA.png!web

有8个数组成一个无序数列:5,8,6,3,9,2,1,7,希望从小到大排序。 按照冒泡排序的思想,我们要把相邻的元素两两比较,根据大小来交换元素的位置,过程如下:

首先让5和8比较,发现5比8要小,因此元素位置不变。

接下来让8和6比较,发现8比6要大,所以8和6交换位置。

eYn2mmZ.png!web

eiqyyiA.png!web

继续让8和3比较,发现8比3要大,所以8和3交换位置。

u63muiF.png!web

e2eM3eJ.png!web

继续让8和9比较,发现8比9要小,所以元素位置不变。

接下来让9和2比较,发现9比2要大,所以9和2交换位置。

VnI3qyv.png!web

jEnqa2j.png!web

接下来让9和1比较,发现9比1要大,所以9和1交换位置。

RZnaIvY.png!web

EzQrQj2.png!web

最后让9和7比较,发现9比7要大,所以9和7交换位置。

yYryAbv.png!web

biAveaV.png!web

这样一来,元素9作为数列的最大元素,就像是汽水里的小气泡一样漂啊漂,漂到了最右侧。

这时候,我们的冒泡排序的第一轮结束了。数列最右侧的元素9可以认为是一个有序区域,有序区域目前只有一个元素。

3m2yuuJ.png!web

下面,让我们来进行第二轮排序:

首先让5和6比较,发现5比6要小,因此元素位置不变。

接下来让6和3比较,发现6比3要大,所以6和3交换位置。

E7fUJra.png!web

qEbu6jV.png!web

继续让6和8比较,发现6比8要小,因此元素位置不变。

接下来让8和2比较,发现8比2要大,所以8和2交换位置。

2EFv22V.png!web

bINVv2a.png!web

接下来让8和1比较,发现8比1要大,所以8和1交换位置。

6j6zIrJ.png!web

EvEZRvV.png!web

继续让8和7比较,发现8比7要大,所以8和7交换位置。

AbyAVzF.png!web

6j63mi6.png!web

第二轮排序结束后,我们数列右侧的有序区有了两个元素,顺序如下:

QFRF7bZ.png!web

至于后续的交换细节,我们这里就不详细描述了,第三轮过后的状态如下:

fE7niuz.png!web

第四轮过后状态如下:

MVVru2i.png!web

第五轮过后状态如下:

vqyyEjM.png!web

第六轮过后状态如下:

7ZRbYvv.png!web

第七轮过后状态如下(已经是有序了,所以没有改变):

jYbQzuU.png!web

第八轮过后状态如下(同样没有改变):

veQ7feM.png!web

到此为止,所有元素都是有序的了,这就是冒泡排序的整体思路。

原始的冒泡排序是稳定排序。由于该排序算法的每一轮要遍历所有元素,轮转的次数和元素数量相当,所以时间复杂度是O(N^2) 。

vmIfmuF.jpg!web

nu6juqe.png!web

冒泡排序代码及优化

冒泡排序第一版:

代码非常简单,使用双循环来进行排序。外部循环控制所有的回合,内部循环代表每一轮的冒泡处理,先进行元素比较,再进行元素交换。

nIZviiI.jpg!web

qUreYbR.jpg!web

QbuIrmU.jpg!web

————————————

iiy6j2Q.jpg!web

ZfQ7RnU.jpg!web

RjqIrmB.jpg!web

uuqIbym.jpg!web

原始的冒泡排序有哪些优化点呢?

让我们回顾一下刚才描述的排序细节,仍然以5,8,6,3,9,2,1,7这个数列为例,当排序算法分别执行到第六、第七、第八轮的时候,数列状态如下:

YNJrYze.png!web

很明显可以看出,自从经过第六轮排序,整个数列已然是有序的了。可是我们的排序算法仍然“兢兢业业”地继续执行第七轮、第八轮。

这种情况下,如果我们能判断出数列已经有序,并且做出标记,剩下的几轮排序就可以不必执行,提早结束工作。

冒泡排序第二版

这一版代码做了小小的改动,利用布尔变量isSorted作为标记。如果在本轮排序中,元素有交换,则说明数列无序;如果没有元素交换,说明数列已然有序,直接跳出大循环。

Z7vy2m6.jpg!web

ymuymiI.jpg!web

为了说明问题,咱们这次找一个新的数列:

uMrQziA.png!web

这个数列的特点是前半部分(3,4,2,1)无序,后半部分(5,6,7,8)升序,并且后半部分的元素已经是数列最大值。

让我们按照冒泡排序的思路来进行排序,看一看具体效果:

第一轮

元素3和4比较,发现3小于4,所以位置不变。

元素4和2比较,发现4大于2,所以4和2交换。

IBBFRry.png!web

iI7bIfz.png!web

元素4和1比较,发现4大于1,所以4和1交换。

a22aauA.png!web

UbE3I36.png!web

元素4和5比较,发现4小于5,所以位置不变。

元素5和6比较,发现5小于6,所以位置不变。

元素6和7比较,发现6小于7,所以位置不变。

元素7和8比较,发现7小于8,所以位置不变。

第一轮结束,数列有序区包含一个元素:

ZRZvE3q.png!web

第二轮

元素3和2比较,发现3大于2,所以3和2交换。

2aqYreA.png!web

QRnqmua.png!web

元素3和1比较,发现3大于1,所以3和1交换。

RNZZnyb.png!web

uiuYjan.png!web

元素3和4比较,发现3小于4,所以位置不变。

元素4和5比较,发现4小于5,所以位置不变。

元素5和6比较,发现5小于6,所以位置不变。

元素6和7比较,发现6小于7,所以位置不变。

元素7和8比较,发现7小于8,所以位置不变。

第二轮结束,数列有序区包含一个元素:

zIBr6jn.png!web

Jb6jq2y.jpg!web

UFVva2z.jpg!web

Zryy6b2.jpg!web

这个问题的关键点在哪里呢?关键在于对数列有序区的界定。

按照现有的逻辑,有序区的长度和排序的轮数是相等的。比如第一轮排序过后的有序区长度是1,第二轮排序过后的有序区长度是2 ......

实际上,数列真正的有序区可能会大于这个长度,比如例子中仅仅第二轮,后面5个元素实际都已经属于有序区。因此后面的许多次元素比较是没有意义的。

如何避免这种情况呢?我们可以在每一轮排序的最后,记录下最后一次元素交换的位置,那个位置也就是无序数列的边界,再往后就是有序区了。

冒泡排序第三版

这一版代码中,sortBorder就是无序数列的边界。每一轮排序过程中,sortBorder之后的元素就完全不需要比较了,肯定是有序的。

7nQrEz6.jpg!web

本漫画纯属娱乐,还请大家尽量珍惜当下的工作,切勿模仿小灰的行为哦。

作者:小灰,本文经授权转自程序员小灰公众号。

AFrURf2.gif

ZjM7fmJ.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK