跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言AI算法

高级人工智能期末复习:搜索算法

涵盖状态空间搜索基础,对比树搜索与图搜索差异,介绍 DFS、BFS 及改进策略。重点解析 A*算法原理,包括 f(n)=g(n)+h(n) 机制,证明启发函数可采纳性与一致性对最优解的影响。最后简述局部搜索方法如爬山法、模拟退火及遗传算法,并提供核心算法对比总结。

晚风告白发布于 2026/2/10更新于 2026/5/3019 浏览
高级人工智能期末复习:搜索算法

先看老师画的重点

状态搜索

状态搜索是搜索最基本的类型。它通过在状态空间中的初始状态出发,按照一定的顺序和条件对空间中的状态进行遍历,最终找到目标状态。

树搜索

1. 核心定义

将状态搜索问题抽象为树状层级结构:

  • 根节点对应初始状态,所有节点代表具体状态;
  • 树枝对应状态转移的动作 / 路径;
  • 前沿(Fringe):存储待扩展的节点集合;
  • 搜索逻辑:从根节点(初始状态)开始扩展节点,当前沿中出现目标状态时,停止搜索并返回路径。
2. 流程
function Tree-Search(problem, fringe) returns 解/失败
    fringe ← 加入初始状态节点
    loop do
        若前沿为空则返回失败
        取出前沿首节点
        若该节点是目标状态则返回
        扩展该节点的所有后继节点,加入前沿
3. 不足

无状态去重机制,同一状态可能重复进入前沿,导致冗余扩展(如迷宫中同一位置被多次探索)

图搜索

1. 核心定义

是树搜索的改进版,新增封闭集(closed)—— 存储已扩展的状态,避免重复探索同一状态。

2. 流程
function Graph-Search(problem, fringe) returns 解/失败
    closed ← 空集合
    fringe ← 加入初始状态节点
    loop do
        若前沿为空则返回失败
        取出前沿首节点
        若该节点是目标状态则返回
        若该节点状态不在 closed 中:
            将状态加入 closed
            扩展该节点的所有后继节点,加入前沿
3. 不足

可能错过最优解(因为每个节点只搜索一次)

树搜索与图搜索的区别与联系

联系
  • 图搜索基于树搜索框架设计,核心流程(初始化前沿、循环取节点、目标测试、扩展节点)与树搜索一致;
  • 两者均通过'前沿'管理待扩展节点,本质是遍历所有可能状态以寻找目标。
区别
维度树搜索图搜索
状态去重机制无封闭集,可能重复扩展同一状态有 closed 集合,避免重复扩展
空间复杂度较低(无额外存储)较高(需存储 closed 集合)
适用场景状态无重复的问题存在重复状态的问题(如路径规划)
搜索效率可能因冗余扩展降低效率因去重机制效率更高

搜索策略评价

评价一个搜索算法,从四个维度进行——完备性、最优性、空间复杂度、时间复杂度

  • 完备性:只要问题有解,算法能不能一定找到?(比如找钥匙,能不能保证找到,不管钥匙藏在哪)
  • 最优性:找到的解是不是'最好的'?(比如找最短路径,能不能找到距离最短 / 代价最小的)
  • 时间复杂度:找解要花多久?(用'搜索的节点数'衡量,节点越多越慢)
  • 空间复杂度:找解要占多少内存?(用'同时记住的节点数'衡量,记的节点越少越省内存)

传统基础搜索

这类算法只知道'初始状态、目标状态、能做什么动作',不知道'当前状态离目标多远',像瞎摸一样找路。

深度优先搜索 DFS

不具备完备性、最优性,但空间复杂度良好

  • 优点:空间复杂度低。只需要记当前路径上的节点,不用记所有探索过的节点(比如迷宫里只记'现在在哪、走过哪些岔路')。
  • 缺点:① 不完备:如果迷宫有无限长的路,会一直走下去,永远找不到出口;② 不最优:可能找到一条绕远的路就停了,没机会找更短的。
广度优先搜索 BFS

具备完备性、最优性,但空间复杂度很高

  • 优点:① 完备性:只要有出口,一定能找到(不会漏层);② 最优性:如果每步代价相同(比如每段路距离一样),找到的一定是最短路径(步数最少)。
  • 缺点:空间复杂度极高!要记所有已经探索过的'层',节点多了会占满内存(比如迷宫大了,要记上百个岔路)。

改进搜索

迭代深入搜索

结合 DFS 的空间优势和 BFS 的时间优势,先做'深度限制为 1 的 DFS'(只走 1 步就回头),没找到就做'深度限制为 2 的 DFS',依次增加深度,直到找到目标。

代价一致搜索(Dijkstra 算法)

找路时,不看走了多少步,只看从起点到当前节点的'总距离',总距离最小的节点先探索。比 BFS 更通用,适合'每步代价不同'的情况,如果每步代价相同,代价一致就和 BFS 一样。

启发式搜索——A*算法

传统搜索没有考虑本身信息,不会用'当前节点离目标有多远',就像没导航找路,瞎转悠。启发式搜索会用'导航'(启发式函数),效率大幅提升。

A*算法是启发式搜索的最优算法,核心目标是'在初始状态到目标状态的所有可能路径中,高效找到代价最小的最优路径'。它不像盲搜(BFS/DFS)那样'瞎转悠',而是通过'已走的实际代价 + 到目标的估计代价'综合判断节点优先级,既保证最优性,又大幅提升搜索效率,相当于'带精准导航的找路算法'。

首先先由一个例子介绍一下 A*算法的执行过程,再证明其最优性。

A*算法涉及 3 个函数,其中,最终决定下一步走哪里的是 f(n)

  • g(n):从初始节点到当前节点 n的实际代价(固定值,路径确定则 g(n) 唯一);
  • h(n):从当前节点 n到目标节点的估计代价(启发函数,决定 A*效率与最优性);
  • f(n):从初始节点经 n 到目标的总代价估计,A*每次优先扩展 f(n) 最小的节点。
算法执行过程

目标:从城市 Arad 到 Bucharest 的最优路线。

为了实现这个目标,需要维护一个优先队列,该队列按节点的 f 值升序排列,当前对头即为下一步需要处理的节点。还需要维护一个关闭列表,记录已经遍历过的节点。

  • 优先队列(fringe):存储待扩展节点,按 f(n) 升序排列

    • 初始队列:[Arad(g=0,h=366,f=0+366=366)]
  • 关闭列表(closed):存储已扩展节点,初始为空

  • 逻辑:初始节点 Arad 无前置路径,g=0,h=366(Arad 到 B 的直线距离),f=366 为当前唯一节点。

  • 选中节点:队列中 f 最小的 Arad,将其加入关闭列表(closed={Arad})

  • 扩展 Arad 的 3 个邻居,计算每个邻居的 g、h、f:

    1. Zerind(Z):g=Arad 的 g+75=0+75=75;h=374(Z 到 B 的直线距离);f=75+374=449
    2. Sibiu(S):g=0+140=140;h=253(S 到 B 的直线距离);f=140+253=393
    3. Timisoara(T):g=0+118=118;h=329(T 到 B 的直线距离);f=118+329=447
  • 更新队列(按 f 升序):[Sibiu(393)、Timisoara(447)、Zerind(449)]

  • 选中节点:队列中 f 最小的 Sibiu,加入关闭列表(closed={Arad、Sibiu})

  • 扩展 Sibiu 的 4 个邻居(Arad 已在 closed,跳过):

    1. Fagaras(F):g=140+99=239;h=176(F 到 B 的直线距离);f=239+176=415
    2. Oradea(O):g=140+92=232;h=380(O 到 B 的直线距离);f=232+380=612
    3. Rimnicu Vilcea(R):g=140+80=220;h=193(R 到 B 的直线距离);f=220+193=413
  • 更新队列(按 f 升序):[Rimnicu Vilcea(413)、Fagaras(415)、Timisoara(447)、Zerind(449)、Oradea(612)]

  • 选中节点:队列中 f 最小的 Rimnicu Vilcea,加入关闭列表(closed={Arad、Sibiu、Rimnicu Vilcea})

  • 扩展 Rimnicu Vilcea 的 3 个邻居(Sibiu 已在 closed,跳过):

    1. Pitesti(P):g=220+97=317;h=100(P 到 B 的直线距离);f=317+100=417
    2. Craiova(C):g=220+146=366;h=160(C 到 B 的直线距离);f=366+160=526
  • 更新队列(按 f 升序):[Fagaras(415)、Pitesti(417)、Timisoara(447)、Zerind(449)、Craiova(526)、Oradea(612)]

  • 选中节点:队列中 f 最小的 Fagaras,加入关闭列表(closed={Arad、Sibiu、Rimnicu Vilcea、Fagaras})

  • 扩展 Fagaras 的 2 个邻居(Sibiu 已在 closed,跳过):

    1. Bucharest(B):g=239+211=450;h=0(目标节点 h=0);f=450+0=450
  • 更新队列(按 f 升序):[Pitesti(417)、Timisoara(447)、Zerind(449)、Bucharest(450)、Craiova(526)、Oradea(612)]

  • 关键:此时 Bucharest 已加入队列,但 f=450 并非当前最小,不选中。

  • 选中节点:队列中 f 最小的 Pitesti,加入关闭列表(closed={Arad、Sibiu、Rimnicu Vilcea、Fagaras、Pitesti})

  • 扩展 Pitesti 的 2 个邻居(Rimnicu Vilcea 已在 closed,跳过):

    1. Bucharest(B):g=317+101=418;h=0;f=418+0=418
  • 更新队列:此时 Bucharest 有两个路径记录(Fagaras→B:f=450;Pitesti→B:f=418),队列按 f 升序更新为 [Bucharest(418)、Timisoara(447)、Zerind(449)、Bucharest(450)、Craiova(526)、Oradea(612)]

此时继续执行选中节点:队列中 f 最小的 Bucharest(f=418),Bucharest 是目标节点,算法终止 最优路径:Arad→Sibiu→Rimnicu Vilcea→Pitesti→Bucharest,总实际代价 g=418。

为什么 A*算法得到的一定是最优解?

对于树搜索和图搜索来说,A*算法得到最优解的条件是不太一样的,树搜索的要求更低一些:

A*图搜索的最优性条件:启发函数 h(n) 满足'一致性'

从 A*涉及到的三个函数来说,很明显可以看到h(n)是其中最关键的(g(n)是已知条件,f(n)只是用来求和,因此如何设计一个合理的 h(n)是最重要的)低估或者高估 h(n)都会对算法的性能造成影响。

因此A*算法要保证找到最优解,核心条件是启发函数 h(n) 满足'一致性',具体如下:

  1. 一致性(Consistency)定义:通俗来说,就是当前节点到目标的估计代价,不能比'先到相邻节点的实际代价 + 相邻节点到目标的估计代价'还大。
  2. 一致性的作用:
    • 保证f(n)沿路径单调不减(f(n') = g(n') + h(n') = g(n') = g(n) + (从 n 到 n'的实际一步代价) + h(n') ≥ g(n)+h(n) = f(n));
    • 节点首次被扩展时,g(n)已是初始到 n 的最小实际代价,无需重复更新;
    • 目标节点首次被扩展时,其f(n)=g(n)(h(目标)=0)必为最小总代价,即最优路径。

注意:仅满足**'可采纳性'(h(n)≤h*(n),h*(n) 为 n 到目标的实际最小代价)**不足以保证图搜索最优,因可能重复扩展节点导致错过最优路径;但'一致性'是更强的约束——一致的 h(n) 必可采纳,可同时满足图搜索的最优性与效率。

*一致性证明

即证明:保证f(n)沿路径单调不减:f(n') >= f(n)

符号定义与推导如下,不再过多赘述:

f(n') = g(n') + h(n') = g(n') = g(n) + (从 n 到 n'的实际一步代价) + h(n') ≥ g(n)+h(n) = f(n)

证明:树搜索 A*算法在 h(n) 可采纳时最优

证明该问题前,需要由如下概念引入:

  • 可采纳性:启发函数h(n) ≤ h*(n),其中h*(n)是节点 n 到目标节点的实际最小代价(即 n 到目标的最短路径代价)。
  • 最优路径代价:设C*为初始节点到目标节点的实际最小总代价,G*为最优目标节点(即沿最优路径到达的目标节点,其g(G*)=C*)。
  • 子最优目标节点:设G2为任意非最优的目标节点,(**即沿非最优路径到达的目标节点)**其g(G2) > C*(即路径代价大于最优值)。
  • f(n) 的定义:f(n) = g(n) + h(n),其中g(n)是初始节点到 n 的实际路径代价。

A算法会根据 f(n) 的值来选择下一个节点,我们需要证明:**当 h(n) 可采纳时,树搜索的 A会优先扩展最优路径上的节点,最终找到最优目标节点 G*,而非次最优节点 G2**。即 f(n) < f(G2) 恒成立。

步骤 1:最优路径上始终存在未扩展节点
  • 初始时,初始节点在最优路径上,且是未扩展节点。
  • 假设某一时刻,最优路径上的节点n被 A*扩展:由于树搜索的后继函数会生成n的相邻节点,其中必有一个节点n'仍在最优路径上(否则该路径不是最优),因此n'会被加入待扩展队列,成为新的未扩展节点。
  • 结论:在 A*终止前,最优路径上必然存在至少一个未扩展节点。
步骤 2:最优路径上未扩展节点的 f(n) ≤ C*

设n是最优路径上的任意未扩展节点,需证明f(n) ≤ C*:

  • 由于n在最优路径上,g(n)是初始节点到 n 的实际代价,而g*(n)是初始到 n 的实际最小代价(因 n 在最优路径上,故g(n)=g*(n))。
  • 由 h(n) 的可采纳性(h(n) ≤ h*(n)),h*(n)是n到 G*的实际最小代价。
  • 因此:f(n)=g(n)+h(n)=g∗(n)+h(n)≤g∗(n)+h∗(n)
  • 而g*(n) + h*(n)正是初始节点经 n 到 G*的实际最小总代价,即C*(最优路径代价)。
  • 结论:f(n) ≤ C*。
步骤 3:次最优目标节点的 f(G2) > C*

设G2是任意次最优目标节点(g(G2) > C*),需证明f(G2) > C*:

  • 目标节点的h(G2)=0(已到达目标,无需再估计代价),因此:f(G2)=g(G2)+h(G2)=g(G2)
  • 由于G2是次最优节点,g(G2) > C*,因此:f(G2)=g(G2)>C∗
步骤 4:A会优先扩展最优路径的节点,最终找到 G

A*的扩展规则是:每次选择待扩展队列中 f(n) 最小的节点。结合步骤 2 和步骤 3 的结论:

  • 最优路径上未扩展节点的f(n) ≤ C*;
  • 子最优目标节点的f(G2) > C*。

因此,次最优目标节点 G2 的 f 值,必然大于最优路径上未扩展节点的 f 值。这意味着:A*会优先扩展最优路径上的节点,而不会先扩展子最优节点 G2。

随着最优路径上的节点不断被扩展,最终会扩展到最优目标节点 G*,此时f(G*) = g(G*) + h(G*) = C* + 0 = C*(是当前最小的 f 值),算法终止。

例如 PPT 中的例子

最优目标节点 G 指'通过最优路径到达的 Bucharest',次最优节点 G2 指'通过非最优路径到达的同一个 Bucharest':

  • 最优路径:Arad→Sibiu→Rimnicu Vilcea→Pitesti→Bucharest,C*=418。
  • 最优路径上的节点Sibiu:g(Sibiu)=140,h(Sibiu)=253(可采纳,因253 ≤ 实际到 Bucharest 的代价),故f(Sibiu)=140+253=393 ≤ 418。
  • 子最优路径(如Arad→Timisoara→Lugoj→Mehadia→Drobeta→Craiova→Pitesti→Bucharest):其目标节点的g(G2) > 418,故f(G2) > 418。

A*会优先扩展f=393的Sibiu,而非f>418的子最优节点,最终找到最优路径。

最优化搜索

局部搜索不关心从初始状态到目标的'路径',只关心'找到最好的状态'

1. 爬山搜索:'贪心爬楼梯'
  • 通俗理解:从当前状态出发,选'最好的邻居状态'(比如 8 拼图中,离目标布局更近的),一直往上爬,直到'没有更好的邻居'(到顶了)。
  • 优点:简单、省内存。
  • 缺点:容易困在'局部最高点'(比如爬了个小土坡,以为是山顶,其实旁边有更高的山),不完备、不最优。
2. 模拟退火:'允许偶尔下坡的爬山法'
  • 通俗理解:像金属退火时'先高温软化,再低温定型',搜索初期允许'选差一点的邻居'(下坡),避免困在局部最高点;后期慢慢不允许下坡,专注找全局最优。
  • 优点:比爬山法更容易找到全局最优。
  • 例子:找函数最大值,爬山法可能卡在小山峰,模拟退火会偶尔'往下走一步',再找到更高的山峰。
3. 遗传算法:'模拟生物进化'
  • 通俗理解:把每个'状态'看成'生物个体'(比如 8 皇后的布局是一个个体),多个个体组成'种群'。通过'繁殖(交叉)、变异'产生新一代个体,再留下'适应度高'(比如不冲突的皇后对多)的个体,逐代进化,直到找到最优个体。
  • 核心步骤:
    1. 编码:把状态变成'染色体'(比如 8 皇后用 8 位数字表示每列皇后的行号)。
    2. 适应度函数:判断个体好不好(比如 8 皇后中,不冲突的皇后对数量)。
    3. 遗传操作:
      • 交叉:两个优秀个体交换部分'基因'(比如两个布局交换后 4 列的皇后位置)。
      • 变异:偶尔改变一个'基因'(比如随机改一列皇后的行号)。
  • 优点:适合复杂的优化问题(比如卫星天线设计、高铁车头形状优化),能找到全局最优。

所有搜索算法核心对比表

例题

w = 0,f(n) = 2 * g(n),此时相当于只关注当下;w = 2,f(n) = 2 * h(n),此时相当于只关注目标。

  1. 可采纳(admissible):小于等于即 B 到 G 的最短路程
  • 路径 B→C→D→F→G:1+3+3+5=12
  • 路径 B→C→D→G:1+3+9=13
  • 路径 B→D→F→G:5+3+5=13
  • 路径 B→D→G:5+9=14

因此,0≤h(B)≤12

  1. 一致(consistent):当前节点到目标的估计代价,不能比'先到相邻节点的实际代价 + 相邻节点到目标的估计代价'还大。

因此,0≤h(B)≤10

  1. 验证启发函数的性质:在实际应用中,通常优先选择满足一致性条件的启发函数,以确保图搜索下的最优性和效率。若仅满足可采纳性,树搜索仍能保证最优,但图搜索可能需要重新开放节点。

目录

  1. 状态搜索
  2. 树搜索
  3. 1. 核心定义
  4. 2. 流程
  5. 3. 不足
  6. 图搜索
  7. 1. 核心定义
  8. 2. 流程
  9. 3. 不足
  10. 树搜索与图搜索的区别与联系
  11. 联系
  12. 区别
  13. 搜索策略评价
  14. 传统基础搜索
  15. 深度优先搜索 DFS
  16. 广度优先搜索 BFS
  17. 改进搜索
  18. 迭代深入搜索
  19. 代价一致搜索(Dijkstra 算法)
  20. 启发式搜索——A*算法
  21. 算法执行过程
  22. 为什么 A*算法得到的一定是最优解?
  23. A*图搜索的最优性条件:启发函数 h(n) 满足“一致性”
  24. *一致性证明
  25. 证明:树搜索 A*算法在 h(n) 可采纳时最优
  26. 步骤 1:最优路径上始终存在未扩展节点
  27. 步骤 2:最优路径上未扩展节点的 f(n) ≤ C*
  28. 步骤 3:次最优目标节点的 f(G2) > C*
  29. 步骤 4:A会优先扩展最优路径的节点,最终找到 G
  30. 最优化搜索
  31. 1. 爬山搜索:“贪心爬楼梯”
  32. 2. 模拟退火:“允许偶尔下坡的爬山法”
  33. 3. 遗传算法:“模拟生物进化”
  34. 所有搜索算法核心对比表
  35. 例题
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 【选型】地瓜机器人RDK系列选型指南:X3 vs X5 vs S100 vs S100P(含资源对比图)
  • 地瓜机器人 RDK 系列选型指南:X3 vs X5 vs S100 vs S100P
  • AI 商业价值与盈利趋势深度解析
  • Android IM 即时通讯应用开发实战:基于 Smack 与 Openfire
  • Android 开发:基于 ListView 实现简易备忘录
  • MK SD NAND:无人机飞控日志存储方案
  • PUBG 压枪宏配置教程:Logitech 鼠标自动识别与参数设置
  • DeepSeek-R1 大模型基于 MS-Swift 框架部署与微调实践
  • Windows 系统安装与配置 Neo4j 图数据库指南
  • 线性代数导引:可构造数域 K
  • 递归算法专题:汉诺塔、链表操作与快速幂
  • Vivado 中 Block Memory IP 核配置与读写控制
  • 利用 Python 和 Kivy 开发移动端应用实战指南
  • 小窝 AI v1.0.0 应用介绍:内置多模型 AI 虚拟伴侣
  • 2026 年 6 款主流免费 AI 写作工具实测与去 AI 味方案
  • 二级 Python 考试真题及参考代码合集(基本操作题)
  • C++ 数据结构:哈希表原理及 STL 实现
  • Ubuntu 22.04 下基于 ROS2 Humble 的 PX4 仿真环境搭建
  • cann-recipes-train 实战:昇腾平台 DeepSeek-R1 与 Qwen2.5 强化学习优化
  • CentOS 7 忘记 root 密码的重置方法

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online