元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
算法基础
▶
复杂度分析
时间复杂度
空间复杂度
渐进符号
▶
算法思想
分治法
贪心算法
回溯法
概率算法
枚举算法
递推算法
递归算法
动态规划
分支限界法
模拟算法
▶
算法分析
正确性证明
性能优化
算法比较
▶
搜索算法
▶
基本搜索
顺序搜索
二分搜索
插值搜索
▶
图搜索
深度优先搜索
广度优先搜索
启发式搜索
▶
高级搜索
双向搜索
A*算法
模式匹配
▶
排序算法
▶
比较类排序
冒泡排序
快速排序
归并排序
插入排序
选择排序
▶
非比较类排序
计数排序
基数排序
桶排序
▶
高级排序
堆排序
希尔排序
外部排序
拓扑排序
▶
图论算法
▶
图的表示
邻接矩阵
邻接表
边集数组
▶
最短路径
Dijkstra算法
Floyd算法
Bellman-Ford算法
最短路径概述
▶
生成树
Prim算法
Kruskal算法
并查集
最小生成树
▶
图的连通性
强连通分量
割点与桥
双连通分量
欧拉路径
▶
动态规划
▶
基础概念
最优子结构
重叠子问题
状态转移方程
▶
经典问题
背包问题
最长公共子序列
编辑距离
▶
优化技巧
空间优化
状态压缩
区间动态规划
▶
字符串算法
▶
字符串匹配
KMP算法
Boyer-Moore算法
Sunday算法
▶
字符串处理
字典树
后缀数组
字符串哈希
▶
压缩算法
游程编码
Huffman编码
LZ77算法
发布时间:
2025-03-21 18:28
↑
☰
# 启发式搜索 启发式搜索(Heuristic Search)是一种利用问题特定知识来指导搜索方向的算法。它通过评估函数来估计从当前状态到目标状态的代价,从而选择最有希望的路径进行搜索,提高搜索效率。 ## 基本原理 启发式搜索的工作原理如下: 1. 定义问题的状态空间 2. 设计启发函数(评估函数) 3. 根据启发函数的评估值选择下一个要探索的状态 4. 不断重复,直到找到目标状态或确定无解 ## 代码实现 ### 基本实现(贪心最佳优先搜索) ```python from heapq import heappush, heappop class Node: def __init__(self, state, parent=None, cost=0, heuristic=0): self.state = state self.parent = parent self.cost = cost self.heuristic = heuristic self.total_cost = cost + heuristic def __lt__(self, other): return self.total_cost < other.total_cost def best_first_search(start_state, goal_state, get_neighbors, heuristic): start_node = Node(start_state, None, 0, heuristic(start_state, goal_state)) frontier = [start_node] explored = set() while frontier: current = heappop(frontier) if current.state == goal_state: return get_path(current) explored.add(str(current.state)) for neighbor_state, step_cost in get_neighbors(current.state): if str(neighbor_state) in explored: continue neighbor = Node( neighbor_state, current, current.cost + step_cost, heuristic(neighbor_state, goal_state) ) heappush(frontier, neighbor) return None def get_path(node): path = [] while node: path.append(node.state) node = node.parent return path[::-1] # 使用示例:8数码问题 def manhattan_distance(state, goal): distance = 0 size = int(len(state) ** 0.5) for i in range(len(state)): if state[i] == 0: # 空格 continue current_row = i // size current_col = i % size value = state[i] goal_idx = goal.index(value) goal_row = goal_idx // size goal_col = goal_idx % size distance += abs(current_row - goal_row) + abs(current_col - goal_col) return distance def get_8puzzle_neighbors(state): neighbors = [] size = int(len(state) ** 0.5) empty = state.index(0) row = empty // size col = empty % size # 可能的移动方向:上、下、左、右 directions = [ (-1, 0), (1, 0), (0, -1), (0, 1) ] for dx, dy in directions: new_row = row + dx new_col = col + dy if 0 <= new_row < size and 0 <= new_col < size: new_empty = new_row * size + new_col new_state = list(state) new_state[empty], new_state[new_empty] = \ new_state[new_empty], new_state[empty] neighbors.append((tuple(new_state), 1)) return neighbors # 使用示例 start_state = (7, 2, 4, 5, 0, 6, 8, 3, 1) goal_state = (0, 1, 2, 3, 4, 5, 6, 7, 8) path = best_first_search( start_state, goal_state, get_8puzzle_neighbors, manhattan_distance ) if path: print("找到解决方案:") for i, state in enumerate(path): print(f"步骤 {i}:") for j in range(0, 9, 3): print(state[j:j+3]) print() else: print("没有找到解决方案") ``` ## 性能分析 ### 时间复杂度 - 最好情况:O(b * d),其中b是分支因子,d是解的深度 - 最坏情况:O(b^d),类似于盲目搜索 - 平均情况:取决于启发函数的质量 ### 空间复杂度 - O(b^d),需要存储搜索过程中的所有节点 ### 优缺点分析 优点: 1. 搜索效率高于盲目搜索 2. 可以利用问题特定知识 3. 灵活性强,可以根据需求设计启发函数 4. 适合解决复杂的优化问题 缺点: 1. 启发函数的设计难度大 2. 不保证找到最优解 3. 可能陷入局部最优 4. 内存消耗较大 ## 应用场景 1. 路径规划 2. 游戏AI 3. 组合优化问题 4. 机器学习中的搜索算法 ## 实际应用示例 ### 1. 迷宫寻路 ```python from heapq import heappush, heappop def manhattan_distance(pos1, pos2): return abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1]) def solve_maze_heuristic(maze, start, end): rows, cols = len(maze), len(maze[0]) def is_valid(x, y): return 0 <= x < rows and 0 <= y < cols and maze[x][y] == 0 # 优先队列,存储(f值, g值, 位置, 路径) pq = [(manhattan_distance(start, end), 0, start, [start])] visited = {start} while pq: f, g, current, path = heappop(pq) if current == end: return path # 四个方向:上、右、下、左 directions = [(-1, 0), (0, 1), (1, 0), (0, -1)] for dx, dy in directions: next_x, next_y = current[0] + dx, current[1] + dy next_pos = (next_x, next_y) if is_valid(next_x, next_y) and next_pos not in visited: visited.add(next_pos) new_g = g + 1 new_f = new_g + manhattan_distance(next_pos, end) heappush(pq, (new_f, new_g, next_pos, path + [next_pos])) return None # 使用示例 maze = [ [0, 0, 0, 1, 0], [1, 1, 0, 1, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0] ] start = (0, 0) end = (4, 4) path = solve_maze_heuristic(maze, start, end) if path: print("找到路径:", path) else: print("没有找到路径") ``` ### 2. 旅行商问题 ```python from itertools import permutations def nearest_neighbor_heuristic(distances, start): n = len(distances) unvisited = set(range(n)) - {start} current = start path = [current] total_distance = 0 while unvisited: # 找到最近的未访问城市 next_city = min(unvisited, key=lambda x: distances[current][x]) total_distance += distances[current][next_city] current = next_city path.append(current) unvisited.remove(current) # 返回起点 total_distance += distances[current][start] path.append(start) return path, total_distance # 使用示例 distances = [ [0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0] ] start_city = 0 path, distance = nearest_neighbor_heuristic(distances, start_city) print(f"路径: {path}") print(f"总距离: {distance}") ``` ## 优化技巧 1. 改进启发函数 ```python def combined_heuristic(state, goal): # 结合多个启发函数 h1 = manhattan_distance(state, goal) h2 = misplaced_tiles(state, goal) return max(h1, h2) # 取最大值作为估计 ``` 2. 迭代加深 ```python def iterative_deepening_best_first_search(start, goal, h): threshold = h(start, goal) while True: result = search(start, goal, h, threshold) if result is not None: return result threshold += 1 ``` 3. 双向搜索 ```python def bidirectional_heuristic_search(start, goal, h): forward_frontier = {start: 0} backward_frontier = {goal: 0} while forward_frontier and backward_frontier: if any(node in backward_frontier \ for node in forward_frontier): return reconstruct_path() expand_frontier(forward_frontier, h) expand_frontier(backward_frontier, h) ``` ## 常见问题和解决方案 1. 启发函数设计 - 问题:启发函数不够准确 - 解决:结合多个启发函数 - 使用机器学习训练启发函数 2. 内存消耗 - 问题:存储开销大 - 解决:使用迭代加深 - 定期清理无用节点 3. 局部最优 - 问题:陷入局部最优解 - 解决:随机重启 - 使用禁忌搜索 ## 总结 启发式搜索是一种智能的搜索策略,它通过问题特定的知识来指导搜索方向,提高搜索效率。关键在于设计好的启发函数,使其能够准确估计到目标的距离。在实际应用中,我们需要根据具体问题特点来选择或设计合适的启发函数,并考虑使用各种优化技巧来提高算法的性能。同时,要注意处理好启发函数设计、内存消耗和局部最优等常见问题,确保算法的效果和效率。