排序算法用于将一组数据按某种顺序排列。排序是计算机科学中一个基本的操作,广泛应用于各种应用场景。下面是一些常见的排序算法,包括它们的基本描述、时间复杂度和空间复杂度。
1. 冒泡排序(Bubble Sort)
描述:冒泡排序通过重复交换相邻的未排序元素,将最大(或最小)的元素“冒泡”到序列的一端。
时间复杂度:
- 最坏情况:
O(n^2)
- 平均情况:
O(n^2)
- 最好情况:
O(n)
, 当数组已经排序时(优化版)
空间复杂度:O(1)
代码示例:
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
2. 选择排序(Selection Sort)
描述:选择排序通过不断选择未排序部分中的最小(或最大)元素并放到已排序部分的末尾。
时间复杂度:
- 最坏情况:
O(n^2)
- 平均情况:
O(n^2)
- 最好情况:
O(n^2)
空间复杂度:O(1)
代码示例:
def selection_sort(arr):
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
3. 插入排序(Insertion Sort)
描述:插入排序通过将每个元素插入到前面已排序的部分中,逐步构建有序序列。
时间复杂度:
- 最坏情况:
O(n^2)
- 平均情况:
O(n^2)
- 最好情况:
O(n)
, 当数组已经排序时
空间复杂度:O(1)
代码示例:
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
4. 合并排序(Merge Sort)
描述:合并排序是一个分治算法,递归地将数组分成两半,分别排序后合并。
时间复杂度:
- 最坏情况:
O(n log n)
- 平均情况:
O(n log n)
- 最好情况:
O(n log n)
空间复杂度:O(n)
代码示例:
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
L = arr[:mid]
R = arr[mid:]
merge_sort(L)
merge_sort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] < R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
return arr
5. 快速排序(Quick Sort)
描述:快速排序使用分治策略,选择一个“基准”元素,将数组分成两部分,使得一部分小于基准,另一部分大于基准,然后递归地排序这两部分。
时间复杂度:
- 最坏情况:
O(n^2)
,当每次选择的基准是最小或最大元素时 - 平均情况:
O(n log n)
- 最好情况:
O(n log n)
空间复杂度:O(log n)
(递归调用栈)
代码示例:
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
6. 堆排序(Heap Sort)
描述:堆排序使用堆数据结构,通过构建最大堆或最小堆来排序数组。
时间复杂度:
- 最坏情况:
O(n log n)
- 平均情况:
O(n log n)
- 最好情况:
O(n log n)
空间复杂度:O(1)
代码示例:
def heapify(arr, n, i):
largest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and arr[l] > arr[largest]:
largest = l
if r < n and arr[r] > arr[largest]:
largest = r
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
def heap_sort(arr):
n = len(arr)
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)
for i in range(n-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
heapify(arr, i, 0)
return arr
7. 基数排序(Radix Sort)
描述:基数排序是一种非比较排序算法,通过对每一位数字进行排序来实现。
时间复杂度:
- 最坏情况:
O(n * k)
,其中k
是数字的位数 - 平均情况:
O(n * k)
- 最好情况:
O(n * k)
空间复杂度:O(n + k)
代码示例:
def counting_sort(arr, exp):
n = len(arr)
output = [0] * n
count = [0] * 10
for i in range(n):
index = arr[i] // exp
count[index % 10] += 1
for i in range(1, 10):
count[i] += count[i - 1]
i = n - 1
while i >= 0:
index = arr[i] // exp
output[count[index % 10] - 1] = arr[i]
count[index % 10] -= 1
i -= 1
for i in range(n):
arr[i] = output[i]
def radix_sort(arr):
max_num = max(arr)
exp = 1
while max_num // exp > 0:
counting_sort(arr, exp)
exp *= 10
return arr
总结
- 简单排序(如冒泡、选择、插入排序)适用于小规模数据或教学目的。
- 分治排序(如合并排序、快速排序)适用于中到大规模数据。
- 堆排序和基数排序适用于特定场景,基数排序通常用于处理整数数据。
不同的排序算法有不同的优缺点,选择合适的排序算法可以提高程序的效率和性能。