选择排序:Python 代码示例说明算法

什么是选择排序?

选择排序是一种比较排序算法,用于将随机项目列表按升序排序。比较不需要很多额外的空间。它只需要一个额外的内存空间用于临时变量。

这被称为原地排序。选择排序的时间复杂度为 O(n2),其中 n 是列表中项目的总数。时间复杂度衡量排序列表所需的迭代次数。列表被分成两个部分:第一个列表包含已排序的项目,而第二个列表包含未排序的项目。

默认情况下,已排序列表为空,未排序列表包含所有元素。然后扫描未排序列表以查找最小值,然后将其放入已排序列表中。此过程重复进行,直到所有值都已比较并排序。

选择排序如何工作?

未排序分区中的第一个项目将与右侧的所有值进行比较,以检查它是否是最小值。如果不是最小值,则将其位置与最小值交换。如果最小值的索引是 3,则将索引为 3 的元素的值放在索引 0 处,而索引 0 处的值放在索引 3 处。如果未排序分区中的第一个元素是最小值,则返回其位置。

示例

  • 例如,如果最小值的索引为 3,则将索引为 3 的元素的值放在索引 0 处,而索引 0 处的值放在索引 3 处。如果未排序分区中的第一个元素是最小值,则返回其位置。
  • 然后将已被确定为最小值的元素移到左侧分区,即已排序列表。
  • 分区侧现在有一个元素,而未分区侧有 (n – 1) 个元素,其中 n 是列表中的元素总数。此过程一遍又一遍地重复,直到所有项目都已根据其值进行比较和排序。

问题定义

需要将一列无序的元素按升序排序。以下列表为例。

[21,6,9,33,3]

上面的列表应排序以产生以下结果

[3,6,9,21,33]

解决方案(算法)

步骤 1) 获取 n 的值,即数组的总大小

步骤 2) 将列表划分为已排序和未排序的部分。已排序部分最初为空,而未排序部分包含整个列表

步骤 3) 从未排序部分中选择最小值并将其放入已排序部分。

步骤 4) 重复此过程 (n – 1) 次,直到列表中的所有元素都已排序。

可视化表示

给定一个包含五个元素的列表,下图说明了选择排序算法在排序它们时如何迭代值。

下图显示了未排序列表

Visual Representation

步骤 1)

Visual Representation

第一个值 21 与其余值进行比较,以检查它是否是最小值。

Visual Representation

3 是最小值,因此交换 21 和 3 的位置。带有绿色背景的值表示列表的已排序部分。

步骤 2)

Visual Representation

未排序分区中的第一个值 6 与其余值进行比较,以找出是否存在更小的值

Visual Representation

值 6 是最小值,因此它保持其位置。

步骤 3)

Visual Representation

未排序列表的第一个元素 9 将与其余值进行比较,以检查它是否是最小值。

Visual Representation

值 9 是最小值,因此它在已排序分区中保持其位置。

步骤 4)

Visual Representation

值 33 与其余值进行比较。

Visual Representation

值 21 小于 33,因此交换位置以生成上述新列表。

步骤 5)

Visual Representation

未分区列表中只剩一个值。因此,它已经被排序。

Visual Representation

最终列表与上图所示类似。

使用 Python 3 的选择排序程序

以下代码显示了使用 Python 3 的选择排序实现

def selectionSort( itemsList ):
    n = len( itemsList )
    for i in range( n - 1 ): 
        minValueIndex = i

        for j in range( i + 1, n ):
            if itemsList[j] < itemsList[minValueIndex] :
                minValueIndex = j

        if minValueIndex != i :
            temp = itemsList[i]
            itemsList[i] = itemsList[minValueIndex]
            itemsList[minValueIndex] = temp

    return itemsList


el = [21,6,9,33,3]

print(selectionSort(el))

运行上述代码会产生以下结果

[3, 6, 9, 21, 33]

代码解释

代码解释如下

Selection Sort Program using Python 3

代码解释

  1. 定义一个名为 selectionSort 的函数
  2. 获取列表中元素的总数。我们需要此来确定比较值时要进行的传递次数。
  3. 外循环。使用循环迭代列表中的值。迭代次数为 (n – 1)。n 的值为 5,因此 (5 – 1) 为 4。这意味着外层迭代将执行 4 次。在每次迭代中,变量 i 的值被赋给变量 minValueIndex
  4. 内循环。使用循环将最左边的值与右侧的其他值进行比较。但是,j 的值不从索引 0 开始。它从 (i + 1) 开始。这排除了已排序的值,以便我们专注于尚未排序的项目。
  5. 查找未排序列表中的最小值并将其放置在其正确位置
  6. 当交换条件为真时更新 minValueIndex 的值
  7. 比较 minValueIndex 和 i 的索引号的值,看它们是否不相等
  8. 最左边的值存储在临时变量中
  9. 右侧的较小值首先占据位置
  10. 存储在临时值中的值存储在之前由最小值占据的位置
  11. 将排序后的列表作为函数结果返回
  12. 创建一个名为 el 的列表,其中包含随机数
  13. 在调用 selection Sort 函数并将 el 作为参数传递后,打印排序后的列表。

选择排序的时间复杂度

排序复杂度用于表示排序列表所需的执行次数。实现有两个循环。

逐个选择列表值的外部循环执行 n 次,其中 n 是列表中值的总数。

内部循环将外部循环的值与其余值进行比较,也执行 n 次,其中 n 是列表中元素的总数。

因此,执行次数为 (n * n),也可以表示为 O(n2)。

选择排序有三个复杂度类别:

  • 最坏情况 - 这发生在提供的列表是降序排列的情况下。算法执行的最大执行次数为 [Big-O] O(n2)
  • 最佳情况 - 这发生在提供的列表已排序时。算法执行的最少执行次数为 [Big-Omega] ?(n2)
  • 平均情况 - 这发生在列表是随机顺序的情况下。平均复杂度表示为 [Big-theta] ?(n2)

选择排序的空间复杂度为 O(1),因为它只需要一个用于交换值的临时变量。

何时使用选择排序?

当您想这样做时,最好使用选择排序

  • 您必须将一小部分项目按升序排序
  • 当交换值的成本可以忽略不计时
  • 它还用于需要确保列表中所有值都已被检查的情况。

选择排序的优点

以下是选择排序的优点

  • 它在小型列表中表现出色
  • 它是一种原地算法。它不需要太多空间即可排序。只需要一个额外的空间来保存临时变量。
  • 它在已排序的项目上表现良好。

选择排序的缺点

以下是选择排序的缺点。

  • 在处理大型列表时,它的表现很差。
  • 排序期间的迭代次数为 n 的平方,其中 n 是列表中元素的总数。
  • 与其他算法相比,例如快速排序,其性能更优。

摘要

  • 选择排序是一种原地比较算法,用于将随机列表排序为有序列表。其时间复杂度为 O(n2)
  • 列表被分成两部分:已排序和未排序。从未排序部分中选择最小值并放入已排序部分。
  • 此过程重复进行,直到所有项目都已排序。
  • 使用 Python 3 实现伪代码涉及使用两个 for 循环和 if 语句来检查是否需要交换
  • 时间复杂度衡量排序列表所需的步骤数。
  • 最坏情况时间复杂度发生在列表降序排列时。其时间复杂度为 [Big-O] O(n2)
  • 最佳情况时间复杂度发生在列表已按升序排列时。其时间复杂度为 [Big-Omega] ?(n2)
  • 平均情况时间复杂度发生在列表是随机顺序时。其时间复杂度为 [Big-theta] ?(n2)
  • 当您有少量项目要排序、交换值的成本无关紧要以及必须检查所有值时,选择排序是最佳选择。
  • 选择排序在处理大型列表时表现不佳
  • 与其他排序算法(如快速排序)相比,选择排序的性能较差。