Python 常见的算法可以分为多个类别,包括排序算法、搜索算法、图算法、动态规划、递归算法等。
一、排序算法
1.冒泡排序(Bubble Sort):
原理:冒泡排序通过重复遍历待排序的列表,比较相邻的元素并交换它们的顺序。如果第一个元素比第二个大,就交换它们。这个过程会重复进行,直到没有交换发生,表示列表已经排序完成。
时间复杂度:最坏和平均情况下是O(n²),最好情况下是O(n)。
实现:
def bubble_sort(arr):
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j] # 交换
swapped = True
if not swapped:
break # 如果没有交换,提前结束
return arr
# 示例
print(bubble_sort([64, 34, 25, 12, 22, 11, 90]))
2.选择排序(Selection Sort):
原理:选择排序每次从未排序的部分中选择最小(或最大)元素,将其放到已排序部分的末尾。重复这个过程,直到所有元素都被排序。
时间复杂度:O(n²)。
实现:
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
# 示例
print(selection_sort([64, 25, 12, 22, 11]))
3.快速排序(Quick Sort):
原理:快速排序通过选择一个“基准”元素,将数组分为两部分:小于基准的元素和大于基准的元素。然后递归地对这两部分进行排序。
时间复杂度:平均情况是O(n log n),最坏情况是O(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)
# 示例
print(quick_sort([3, 6, 8, 10, 1, 2, 1]))
4.插入排序(Insertion Sort):
原理:插入排序将数组分为已排序和未排序两部分。每次从未排序部分取出一个元素,插入到已排序部分的合适位置。
时间复杂度:平均和最坏情况是O(n²),最好情况是O(n)。
实现:
def insertion_sort(arr):
n = len(arr)
for i in range(1, n):
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
# 示例
print(insertion_sort([12, 11, 13, 5, 6]))
5. 归并排序(Merge Sort)
原理:归并排序采用分治法,将数组分成两个子数组,分别对这两个子数组进行排序,然后将已排序的子数组合并成一个最终的排序数组。
时间复杂度:O(n log n)。
实现:
def merge_sort(arr):
# 如果数组长度小于等于1,则直接返回
if len(arr) <= 1:
return arr
# 找到中间索引
mid = len(arr) // 2
# 递归地对左右子数组进行排序
left_half = merge_sort(arr[:mid])
right_half = merge_sort(arr[mid:])
# 合并已排序的子数组
return merge(left_half, right_half)
def merge(left, right):
sorted_array = []
i = j = 0
# 合并两个已排序的子数组
while i < len(left) and j < len(right):
if left[i] < right[j]:
sorted_array.append(left[i])
i += 1
else:
sorted_array.append(right[j])
j += 1
# 处理剩余元素
while i < len(left):
sorted_array.append(left[i])
i += 1
while j < len(right):
sorted_array.append(right[j])
j += 1
return sorted_array
# 示例使用
if __name__ == "__main__":
arr = [38, 27, 43, 3, 9, 82, 10]
sorted_arr = merge_sort(arr)
print("排序后的数组:", sorted_arr)
二、搜索算法
1. 线性搜索(Linear Search)
线性搜索是一种简单的搜索算法,它通过逐个检查每个元素来查找目标值。
def linear_search(arr, target):
for index, value in enumerate(arr):
if value == target:
return index # 返回目标值的索引
return -1 # 如果未找到,返回 -1
# 示例
arr = [3, 5, 2, 4, 9]
target = 4
result = linear_search(arr, target)
print(f"目标值 {target} 的索引是: {result}")
2. 二分搜索(Binary Search)
二分搜索是一种高效的搜索算法,适用于已排序的数组。它通过将搜索范围减半来快速定位目标值。
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid # 返回目标值的索引
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1 # 如果未找到,返回 -1
# 示例
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
target = 5
result = binary_search(arr, target)
print(f"目标值 {target} 的索引是: {result}")
3. 深度优先搜索(Depth-First Search, DFS)
深度优先搜索通常用于树或图的遍历。它会尽可能深地搜索树的分支。
def dfs(graph, node, visited=None):
if visited is None:
visited = set()
visited.add(node)
print(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
# 示例
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
dfs(graph, 'A')
4. 广度优先搜索(Breadth-First Search, BFS)
广度优先搜索也是用于树或图的遍历,它逐层访问节点。
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
while queue:
node = queue.popleft()
if node not in visited:
visited.add(node)
print(node)
queue.extend(neighbor for neighbor in graph[node] if neighbor not in visited)
# 示例
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
bfs(graph, 'A')
三、动态规划
斐波那契数列(Fibonacci Sequence):
def fibonacci(n):
if n <= 1:
return n
fib = [0, 1]
for i in range(2, n + 1):
fib.append(fib[i - 1] + fib[i - 2])
return fib[n]
# 示例
print(fibonacci(10)) # 输出: 55
四、 图算法
深度优先搜索(DFS):
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
for neighbor in graph[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
return visited
# 示例
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
print(dfs(graph, 'A')) # 输出: {'A', 'B', 'D', 'E', 'C', 'F'}
五、递归算法
计算阶乘(Factorial)
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
# 示例
print(factorial(5)) # 输出: 120
六、 回溯算法
解决八皇后问题:
def solve_n_queens(n):
def is_safe(board, row, col):
# 检查当前列是否安全
for i in range(row):
if board[i] == col or \
board[i] - i == col - row or \
board[i] + i == col + row:
return False
return True
def solve(board, row):
if row == n:
result.append(board[:])
return
for col in range(n):
if is_safe(board, row, col):
board[row] = col
solve(board, row + 1)
# 在回溯时不需要重置,因为我们直接覆盖
result = []
board = [-1] * n # 初始化棋盘
solve(board, 0)
return result
def print_solutions(solutions):
for board in solutions:
for row in board:
line = ['.'] * len(board)
line[row] = 'Q'
print(' '.join(line))
print()
if __name__ == "__main__":
n = 8 # 八皇后
solutions = solve_n_queens(n)
print(f"找到 {len(solutions)} 种解决方案:")
print_solutions(solutions)