数据结构与算法——12. 冒泡排序和选择排序

文章目录

  • 一、冒泡排序(Bubble Sort)
    • python代码实现
    • 算法分析
    • 改进冒泡排序算法
  • 二、选择排序(Selection Sort)
    • python代码实现
    • 算法分析

排序算法可视化演示:传送门,这些演示可以帮助我们跟好的理解这些排序算法。

下面的算法的实现,均以从小到大排序作为目的。

一、冒泡排序(Bubble Sort)

冒泡排序的算法思路在于对无序表进行多趟比较交换。

每趟包括了多次两两相邻比较,并将逆序的(小项在大项后面的)数据项互换位置,最终能将本趟的最大项就位。

经过n-1趟比较交换,实现整表排序:

  • 第1趟比较交换,共有n-1对相邻数据进行比较。一旦经过最大项,冒泡排序算法就会拿着最大项一个个地跟后面的所有项进行对比、交换。这样,最大项会一路交换到达最后一项。

数据结构与算法——12. 冒泡排序和选择排序_第1张图片

  • 第2趟比较交换时,最大项已经就位,需要排序的数据减少为n-1,共有n-2对相邻数据进行比较。

  • ……

  • 直到第n-1趟完成后,最小项一定在列表首位,就无需再处理了。

python代码实现

def bubble_sort(a_list):
    # 总共进行 n-1 趟排序
    for passnum in range(len(a_list) - 1, 0, -1):
        # 每趟排序到 passnum 停止
        for i in range(passnum):
            if a_list[i] > a_list[i + 1]:
                # 错序,交换
                a_list[i], a_list[i+1] = a_list[i+1], a_list[i]  # python的特有语法,直接交换

算法分析

无序表初始数据项的排列状况对冒泡排序没有影响。

算法过程总需要n-1趟,随着趟数的增加,比对次数逐步从n-1减少到1,并包括可能发生的数据项交换。所以,比对次数是1~n-1的累加: 1 2 n 2 − 1 2 n \frac {1}{2}n^2-\frac {1}{2}n 21n221n对比的复杂度是 O ( n 2 ) O(n^2) O(n2)

关于交换次数,时间复杂度也是 O ( n 2 ) O(n^2) O(n2),通常每次交换包括3次赋值。最好的情况是列表在排序前已经有序,交换次数为0最差的情况是每次比对都要进行交换,交换次数等于比对次数平均情况则是最差情况的一半

冒泡排序是我们能想到的最直观的排序方法,但也是时间效率较差的排序算法。每个数据项在找到其最终位置之前,都需要经过多次比对和交换,重要的是其中大部分的操作是无效的。但有一点优势,就是无需任何额外的存储空间开销

改进冒泡排序算法

我们可以通过监测每趟比对是否发生过交换,提前确定排序是否完成。如果某趟比对没有发生任何交换,说明列表已经排好序,可以提前结束算法。这是其它多数排序算法无法做到的。

def bubble_sort(a_list):
    # 初始化监控交换的变量
    exchanges = True
    passnum = len(a_list) - 1
    while passnum > 0 and exchanges:
        exchanges = False
        for i in range(passnum):
            if a_list[i] > a_list[i + 1]:
                a_list[i], a_list[i+1] = a_list[i+1], a_list[i]
                # 发生交换,修改监控变量
                exchanges = True
        # 需要对比的项目数减一
        passnum -= 1

二、选择排序(Selection Sort)

选择排序对冒泡排序进行了改进,保留了其基本的多趟比对思路。不同之处在于:

  • 冒泡排序每次遇到两个相邻逆序数据项都会进行交换。

  • 而选择排序每趟选择一个最大数据项,直接将它放入合适的位置。

数据结构与算法——12. 冒泡排序和选择排序_第2张图片

python代码实现

def selection_sort(a_list):
    for fillslot in range(len(a_list) - 1, 0, -1):
        # 初始化最大数据项的索引值
        positionOfMax = 0
        # 遍历找出当前的最大数据项
        for location in range(1, fillslot + 1):
            if a_list[location] > a_list[positionOfMax]:
                # 记下最大数据项的索引值
                positionOfMax = location

        # 交换位置
        a_list[fillslot], a_list[positionOfMax] = a_list[positionOfMax], a_list[fillslot]

算法分析

选择排序的时间复杂度比冒泡排序稍优:比对次数不变,还是 O ( n 2 ) O(n^2) O(n2),交换次数则减少为 O ( n ) O(n) O(n)

你可能感兴趣的:(数据结构与算法,算法,数据结构,排序算法)