冒泡排序_Python实现


冒泡排序是最基础的排序算法

什么是冒泡排序??

冒泡排序是一种基础的交换排序

冒泡、冒泡就像水中的气泡一样,不断的往上漂浮,而冒泡算法之所以叫冒泡算法,正是因为这种算法的每一个元素都可以像小气泡一样,一点一点的向数组的一端移动。

冒泡排序的详细过程

我们把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换它们的位置;当一个元素小于或等于右侧相邻的元素时,则位置不变。 详细过程如下:

不断的交换蓝色的数字

58639217
56839217
56389217
56382917
56382197
56382179

从最左端开始,数组中最大的元素9像汽水一起,漂浮到最右端
这时,冒泡排序的第一轮就完成了,有序区域目前就只有一个元素。

56382179

下面,进行第二轮排序:

56382179
53682179
53628179
53621879
53621789

第2轮结束后,数列右侧的有序区有2个元素,顺序如下:

53621789

这样不断的迭代,直到所有的元素都是有序的为止,这就是冒泡排序的整体思想。
冒泡排序是一种稳定的排序,值相等的元素并不会打乱原本的顺序。由于该排序算法每一轮都要遍历所有元素,总共遍历(元素数量-1)轮,所有平均时间复杂度是O(n^2)

代码实现(第一版)

def sort(array):
    for i in range(len(array) - 1):             # 外循环控制所有回合
        for j in range(len(array) -i -1):       # 内循环实现每一轮的冒泡处理
            if array[j] > array[j+1]:           # 如果左大于右,则交换
                array[j],array[j+1] = array[j+1],array[j]
    return array

验证

输入:
array = [5,8,6,3,9,2,1,7]
sort(array)
输出:
[1, 2, 3, 5, 6, 7, 8, 9]

优化(一)

有时,数组中的元素已经排好序了,但是程序还是会继续执行,一直到遍历完所有的轮数(元素个数-1)
在这种情况下,如果可以提前判断数组中元素已经排好序,并标记出来,剩下的轮数就可以不用执行了!

代码实现(第二版)

def sort(array):
    for i in range(len(array) -1):             # 外循环控制所有回合
        issorted = True                        # 判断是否排序好了,初始为true
        for j in range(len(array) -i-1):       # 内循环实现每一轮的冒泡处理
            if array[j] > array[j+1]:          # 如果左大于右,则交换
                array[j],array[j+1] = array[j+1],array[j]
                issorted = False               # 如果有交换,说明没有排好序,则置issorted为False
        if issorted :             # 如果issorted为True说明已经交换完成了,则直接退出循环
            break
    return array

验证

输入:
array = [5,8,6,3,9,2,1,7]
sort(array)
输出:
[1, 2, 3, 5, 6, 7, 8, 9]

相比第一版,第二版做了一些小的改动,利用布尔变量issorted 作为标记。如果在本轮排序中,元素交换,则说明数组无序;如果没有元素交换,则说明数组已经有序,则直接跳出大循环。

优化(二)

用一个新的数组来举例说明:

34215678

我们发现上面数组的左半部分是无序的,右半部分是有序,我们继续采用上面的代码,会出现明明右半部分已经排好序了,但是每一轮中,数组中相邻的元素还是会不断的去比较,故这块可以优化一下。

代码实现(第三版)

def sort(array):
    for i in range(len(array) -1):         # 外循环控制所有回合
        issorted = True                    # 判断是否排序好了,初始为true
        sortBorder = len(array) -1         # 无序数组的边界,每一次更新到这里就结束了
        for j in range(sortBorder):        # 内循环实现每一轮的冒泡处理
            if array[j] > array[j+1]:      # 如果左大于右,则交换
                array[j],array[j+1] = array[j+1],array[j]
                issorted = False           # 如果有交换,说明没有排好序,则置issorted为False
                sortBorder = j             # 将无序数组的边界更新为最后一次交换元素的位置
        if issorted :         # 如果issorted为True说明已经交换了,则直接退出循环
            break
    return array

验证

输入:
array =[3,4,2,1,5,6,7,8]
sort(array)
输出:
[1, 2, 3, 5, 6, 7, 8]

优化二的关键问题在于数列有序区的界定。

按照现在的逻辑,有序区的长度和排序的轮数是一样的,即第一轮排序过后,有序区长度是1,第二轮排序后,有序区长度是2,等等
但实际上,有序区的长度可能要比认定的长度长很多,如上面的例子一样。
那么我们该如何解决呢? 我们可以在每一轮交换完之后,记录一下最后一次元素交换的位置,这个位置就是无序数组和有序数组的界限。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值