1、冒泡排序
冒泡排序是一种简单的排序算法,它的基本思想是比较相邻两个元素的大小,如果顺序不对则交换它们的位置,一直重复这个过程直到整个序列有序。它的时间复杂度为O(n^2),因此对于较大的数据集不太适用,但对于小型数据集和教学目的来说是一种不错的选择。
def bubble_sort(arr):
n = len(arr)
for i in range(n):
# 经过i轮冒泡后,后i个元素已经有序,不需要再比较
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
# 如果前一个元素比后一个元素大,则交换它们的位置
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
在这个示例中,我们首先定义了一个名为bubble_sort
的函数,该函数接收一个列表作为输入参数。函数内部使用两个嵌套的for循环实现冒泡排序。外层循环控制排序轮数,内层循环则负责比较相邻的元素并进行位置交换。具体来说,内层循环从第一个元素开始,比较它和它后面的元素的大小,如果前一个元素比后一个元素大,则交换它们的位置。经过一轮循环后,最后一个元素一定是本轮中最大的元素,因此下一轮循环时只需要比较前n-1个元素即可。
最后,函数返回排序后的列表。
2、选择排序
选择排序(Selection Sort)是一种简单的排序算法,它的基本思路是每次从未排序的数列中选择最小(或最大)的元素,将其放到已排序数列的末尾。重复这个过程,直到所有元素都被排序为止。
具体实现步骤如下:
- 设数组长度为n。
- 从数组中找到最小的元素,并记录其下标。
- 将最小元素与第1个元素交换位置。
- 在剩下的n-1个元素中,找到最小的元素,记录其下标。
- 将最小元素与第2个元素交换位置。
- 重复步骤4-5,直到排序完成。
选择排序是一种简单但效率较低的排序算法,其时间复杂度为O(n^2),不适用于大规模数据的排序。
def selection_sort(arr):
n = len(arr)
for i in range(n):
# 找到未排序部分的最小值
min_index = i
for j in range(i+1, n):
if arr[j] < arr[min_index]:
min_index = j
# 将最小值与当前位置交换
arr[i], arr[min_index] = arr[min_index], arr[i]
return arr
在这个实现中,我们使用了两个循环。外循环从0到n-1遍历数组,表示已排序部分的范围;内循环从i+1到n遍历数组,用于查找未排序部分的最小值。当找到最小值时,我们将其与当前位置进行交换,这样就将最小值放到了已排序部分的末尾。
最后,我们返回排好序的数组。这个实现的时间复杂度为O(n^2),空间复杂度为O(1)。
3、插入排序
插入排序(Insertion Sort)是一种简单直观的排序算法,它的基本思路是将一个未排序的数列,逐个插入到已排序的数列中,使得插入后的数列仍然有序。
具体实现步骤如下:
- 设数组长度为n。
- 将第1个元素看成已排序部分,第2个元素到第n个元素看成未排序部分。
- 从未排序部分取出第1个元素,将其插入已排序部分的合适位置。此时已排序部分的长度为1。
- 从未排序部分取出第2个元素,将其插入已排序部分的合适位置。此时已排序部分的长度为2。
- 重复步骤4,直到所有元素都被插入到已排序部分。
插入排序的优点是实现简单,适用于小规模的数据排序,时间复杂度为O(n^2),空间复杂度为O(1)。但是,对于大规模数据的排序,插入排序的效率较低。
def insertion_sort(arr):
n = len(arr)
for i in range(1, n):
# 获取当前位置的值
key = arr[i]
# 将当前位置的值插入已排序部分的合适位置
j = i - 1
while j >= 0 and arr[j] > key:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
4、快速排序
快速排序(Quicksort)是一种常用的排序算法,其基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序,以达到整个序列有序的目的。
具体实现步骤如下:
- 选取一个基准元素(pivot),通常选择第一个或最后一个元素。
- 将序列中所有元素按照基准元素分成两部分,小于基准元素的放在左边,大于基准元素的放在右边,相等的可以放在任意一边。
- 对左右两部分递归进行快速排序,直到所有元素有序。
-
def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[0] left = [x for x in arr[1:] if x < pivot] right = [x for x in arr[1:] if x >= pivot] return quick_sort(left) + [pivot] + quick_sort(right)
在这个实现中,我们使用了递归的方法实现快速排序。首先,我们选取序列中的第一个元素作为基准元素(pivot),然后将序列中所有小于基准元素的元素放在左边,大于等于基准元素的元素放在右边,相等的元素可以放在任意一边。这一步使用了列表解析的方法,可以比较简洁地实现。最后,我们对左右两部分元素分别进行递归排序,并将结果合并起来,即可得到最终的有序序列。
快速排序的时间复杂度为 O(nlogn),空间复杂度为 O(logn)。在实际应用中,快速排序是一种常用的排序算法,可以用于处理各种规模的数据。
5、堆排序
堆排序(Heap Sort)是一种基于完全二叉树的排序算法,它的基本思想是将待排序的序列看成一棵完全二叉树,并将其构建成一个大根堆(或小根堆),然后将堆顶元素与堆底元素交换,并重新调整堆,使得剩余元素仍满足堆的性质,重复以上操作,直到所有元素有序为止。
具体实现步骤如下:
- 将待排序的序列构建成一个大根堆(或小根堆),这一步可以使用 Heapify 操作实现,即从最后一个非叶子节点开始,依次向下调整每个子树,使其满足堆的性质。
- 将堆顶元素与堆底元素交换,并将堆的大小减一。
- 对堆顶元素进行下沉操作,使其重新满足堆的性质。
- 重复步骤 2 和 3,直到堆的大小为 1,此时整个序列有序。
-
def heap_sort(arr): def heapify(parent): child = 2 * parent + 1 while child < size: if child + 1 < size and arr[child] < arr[child + 1]: child += 1 if arr[child] > arr[parent]: arr[child], arr[parent] = arr[parent], arr[child] parent, child = child, 2 * child + 1 else: break size = len(arr) for i in range(size // 2 - 1, -1, -1): heapify(i) for i in range(size - 1, 0, -1): arr[0], arr[i] = arr[i], arr[0] size -= 1 heapify(0) return arr
在这个实现中,我们首先使用 Heapify 操作将待排序的序列构建成一个大根堆。然后,我们依次将堆顶元素与堆底元素交换,并对堆顶元素进行下沉操作,使其重新满足堆的性质。最后,我们得到了一个有序的序列。
堆排序的时间复杂度为 O(nlogn),空间复杂度为 O(1)。在实际应用中,堆排序是一种常用的排序算法,可以用于处理各种规模的数据。
6、归并排序
归并排序是一种基于分治策略的排序算法。它的基本思想是将待排序的序列不断地分成两个子序列,直到每个子序列只有一个元素,然后将这些子序列进行合并,直到最终得到一个有序序列。
具体来说,归并排序的实现过程如下:
-
分解(Divide):将待排序的序列从中间分成两个子序列,即将序列一分为二,分别对左右两个子序列进行归并排序。
-
合并(Merge):对两个有序的子序列进行合并,得到一个新的有序序列。合并过程中,从两个子序列的头部开始比较每个元素的大小,将较小的元素放入新序列中,直到其中一个子序列为空,然后将另一个子序列中剩余的元素依次放入新序列中。
-
递归(Recursion):重复以上两个步骤,对左右两个子序列分别进行归并排序,直到所有子序列都只有一个元素,排序完成。
归并排序的时间复杂度为O(nlogn),其中n为待排序序列的长度。归并排序是稳定的排序算法,即相等元素的相对位置不会改变。
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left_arr = arr[:mid]
right_arr = arr[mid:]
left_arr = merge_sort(left_arr)
right_arr = merge_sort(right_arr)
return merge(left_arr, right_arr)
def merge(left_arr, right_arr):
i, j = 0, 0
result = []
while i < len(left_arr) and j < len(right_arr):
if left_arr[i] <= right_arr[j]:
result.append(left_arr[i])
i += 1
else:
result.append(right_arr[j])
j += 1
result += left_arr[i:]
result += right_arr[j:]
return result
在这段代码中,merge_sort
函数实现了分解和递归的过程,merge
函数实现了合并的过程。
在merge_sort
函数中,首先判断待排序的序列是否只有一个元素,如果是,直接返回该序列。否则,将序列从中间分成两个子序列,对左右两个子序列分别进行归并排序,然后将结果合并。
在merge
函数中,首先初始化两个指针i
和j
,分别指向左右两个子序列的头部。然后,比较两个指针所指元素的大小,将较小的元素放入结果序列中,并将该序列的指针向后移动一位。重复这个过程直到其中一个子序列为空,然后将另一个子序列中剩余的元素依次放入结果序列中。
最后返回合并后的结果序列即可。