Python 实现排序算法
简介
有时,我们在应用程序中存储或检索的数据有可能是乱序的。如果想要正确处理或者有效使用数据,我们可能需要对数据重新排序。多年来,计算机科学家创造了许多排序算法来处理数据。
在本文中,我们将了解一些流行的排序算法,了解它们是如何工作的,并用 Python 来实现它们。们还将会比较它们对列表中的元素排序的速度。
为了简单起见,这些算法将对列表中的数字都进行升序排序。当然,你可以根据自己的需要来自由调整。
冒泡排序
这个简单的排序算法会通过迭代列表成对的比较列表中的元素,并且交换它们,直到较大的元素“冒泡”到列表的末尾,较小的元素保持在“底部”。
介绍
我们首先比较列表的前两个元素。如果第一个元素大于第二个元素,我们交换它们。如果它们已经排好序,我们将它们保持原样。然后我们移动到下一对元素,比较它们的值,并根据需要交换。这个过程将持续到列表中的最后一对元素。
当到达列表的末尾时,它会对每对元素重复此过程。但是,这个过程是很低效的。如果我们只需要在数组里面进行一次交换怎么办?为什么我们仍然会迭代 n^2 次,即使数组已经排好序了?
显然,为了优化算法,我们需要在完成排序时停止它。
那我们怎么知道已经完成了排序?如果元素是有序的,那我们就不必继续交换。因此,每当交换值时,我们会将一个标志值设置为 True 以重复排序过程。如果没有发生交换,标志值将保持为 False,算法将停止。
实现
优化之后,我们可以通过以下的 Python 代码来实现冒泡排序:
def bubble_sort(nums):
# 我们将标志值 swapped 设为 True,以便循环能够执行至少一次
swapped = True
while swapped:
swapped = False
for i in range(len(nums) - 1):
if nums[i] > nums[i + 1]:
# 交换元素
nums[i], nums[i + 1] = nums[i + 1], nums[i]
# 把标志值设为 True 以便我们能再次循环
swapped = True
# 检查是否能够正确执行
random_list_of_nums = [5, 2, 1, 8, 4]
bubble_sort(random_list_of_nums)
print(random_list_of_nums)
这个算法在一个 while 循环里面运行,仅当没有元素能够交换时才会跳出循环。我们在开始时将 swapped 设为 True,以确保算法至少可以执行一次。
时间复杂度
在最坏的情况下(当列表处于相反的顺序时),该算法必须交换数组的每个项。每次迭代的时候,标志值 swapped 都会被设置为 True。因此,如果我们在列表中有 n 个元素,我们将对每个元素迭代 n 次,因此冒泡排序的时间复杂度为 O(n^2)。
选择排序
该算法将列表分为两部分:已排序部分和未排序部分。我们不断地删除列表中未排序部分的最小元素,并将其添加到已排序部分中。
介绍
实际上,我们并不需要为已排序的元素创建一个新的列表,我们要做的是将列表最左边的部分作为已排序部分。然后我们搜索整个列表中最小的元素,并将其与第一个元素交换。
现在我们知道列表的第一个元素是有序的,我们将继续搜索剩余元素中最小的元素,并将其与第二个元素交换。这将迭代到待检查元素是剩余列表的最后一项时。
实现
def selection_sort(nums):
# i 的值对应于已排序值的数量
for i in range(len(nums)):
# 我们假设未排序部分的第一项是最小的
lowest_value_index = i
# 这个循环用来迭代未排序的项
for j in range(i + 1, len(nums)):
if nums[j] < nums[lowest_value_index]:
lowest_value_index = j
# 将未排序元素的最小的值与第一个未排序的元素的值相交换
nums[i], nums[lowest_value_index] = nums[lowest_value_index], nums[i]
# 检验算法是否正确
random_list_of_nums = [12, 8, 3, 20, 11]
selection_sort(random_list_of_nums)
print(random_li