📜  在Python中进行冒泡排序Bubble Sort

📅  最后修改于: 2020-09-05 11:26:11             🧑  作者: Mango

介绍

对于大多数人来说,Bubble Sort可能是他们在计算机科学课程中听说的第一个排序算法。

它高度直观且易于“转换”为代码,这对于新软件开发人员来说非常重要,因此他们可以轻松地将自己转变为可以在计算机上执行的形式。但是,Bubble Sort在每种情况下都是性能最差的排序算法之一,除了检查数组是否已排序外,在这种情况下,它的性能通常优于快速排序之类的更有效的排序算法。

气泡排序

Bubble Sort背后的想法非常简单,我们查看数组中相邻的元素对,一次查看一对,如果第一个元素大于第二个元素,则交换它们的位置;否则,简单地继续移动。让我们来看一个例子和分类阵列8,5,3,1,4,7,9

如果您专注于第一个数字number,则8可以看到它将数组“冒泡”到正确的位置。然后,对数字重复此过程5,依此类推。

实现

借助可视化功能,让我们继续实施算法。同样,这非常简单: 

def bubble_sort(our_list):
    # We go through the list as many times as there are elements
    for i in range(len(our_list)):
        # We want the last pair of adjacent elements to be (n-2, n-1)
        for j in range(len(our_list) - 1):
            if our_list[j] > our_list[j+1]:
                # Swap
                our_list[j], our_list[j+1] = our_list[j+1], our_list[j]

现在,让我们填充一个列表并在其上调用算法: 

our_list = [19, 13, 6, 2, 18, 8]
bubble_sort(our_list)
print(our_list)

输出: 

[2, 6, 8, 13, 18, 19]

优化

简单的实现可以完成它的工作,但是我们可以在此处进行两个优化。

如果不进行交换,则表示列表已排序。但是,使用以前实现的算法,即使它确实不需要,它也会继续评估列表的其余部分。为了解决这个问题,我们将保留一个boolean标志并检查在先前的迭代中是否进行了任何交换。

如果没有进行交换,则算法应停止:

def bubble_sort(our_list):
    # We want to stop passing through the list
    # as soon as we pass through without swapping any elements
    has_swapped = True

    while(has_swapped):
        has_swapped = False
        for i in range(len(our_list) - 1):
            if our_list[i] > our_list[i+1]:
                # Swap
                our_list[i], our_list[i+1] = our_list[i+1], our_list[i]
                has_swapped = True

我们可以进行的另一种优化利用了这样一个事实,即冒泡排序的工作方式是特定迭代中的最大元素最终出现在数组的末尾。

我们第一次通过列表时,位置n被保证为最大元素,第二次我们通过位置n-1被保证为第二大元素,依此类推。

这意味着,每次连续迭代,我们可以比以前少看一个元素。更准确地说,在第k次迭代中,只需要查看前n-k + 1个元素:

def bubble_sort(our_list):
    has_swapped = True

    num_of_iterations = 0

    while(has_swapped):
        has_swapped = False
        for i in range(len(our_list) - num_of_iterations - 1):
            if our_list[i] > our_list[i+1]:
                # Swap
                our_list[i], our_list[i+1] = our_list[i+1], our_list[i]
                has_swapped = True
        num_of_iterations += 1

时间比较

让我们继续进行比较,并使用以下timeit模块比较这些代码片段对同一列表进行一千次排序所需的时间:

Unoptimized Bubble Sort took: 0.0106407
Bubble Sort with a boolean flag took: 0.0078251
Bubble Sort with a boolean flag and shortened list took: 0.0075207

后两种方法之间的差异不大,因为列表非常短,但是在较大的列表上-第二个优化可以产生很大的差异。

结论

在效率最高的方法中,Bubble Sort进行n-1次迭代,查看n-1对相邻元素。这使它在最佳情况和平均情况下的时间复杂度为O(n 2)。对于排序算法,O(n 2)被认为非常可怕。

它确实具有O(1)的空间复杂性,但这不足以弥补其在其他领域的不足。

但是,它仍然是软件开发社区和历史的重要组成部分,教科书在谈论基本排序算法时几乎从未提及它。