'''
一、简化代码,直接输出路径
'''
class DFSResult():def __init__(self):self.parent = {}self.visited = []def dfs_iterative(graph):results = DFSResult()for v in graph.keys():if v not in results.parent:results.parent[v] = Noneprint("\n%s:" % v, end=" ")if v not in results.visited:stack = [v]while stack:u = stack.pop()if u not in results.visited:results.visited.append(u)print(u, end=", ")for n in graph[u]:if n not in results.visited:results.parent[n]=results.visited[-1]stack.extend(n)return resultsif __name__ == '__main__':graph = {"a": ["b", "d"],"b": ["e"],"d": ["b"],"e": ["d"],"c": ["e", "f"],"f": ["f"]}dfs_iterative(graph)# 输出# a: a, d, b, e, # c: c, f, 

重点问题:

课后习题7-5:给定两个单词(start,end)和一个字典,要求找出从单词start变化到end的最小序列。变化过程中出现的中间单词必须是字典中有的单词,且每次只能是变化其中的一个字母。例如:

start_state = 'hit'
    end_state = 'cog'
    dic = ['hot', 'dot', 'dog', 'lot', 'log']

输出答案为

hit -> hot -> dot -> dog -> cog

本体使用状态机来解决,参考教材“虎胆龙威”例题,本题源码基于“虎胆龙威”例题修改而来。

解题思路:

设问题的状态为一个三元组,如单词'hot'可拆为('h', 'o', 't')表示一个状态,要求hot的下一状态,只需一次变换其每个位置上的字母,将变换后的单词在给定的字典中搜索是否存在,若存在则将该状态保留下来,否则不保留该状态。根据当前状态计算之后的状态,把所有可能的状态变换结果按照变换的先后顺序构建出一个图,利用广度优先搜索算法得出的结果类,找出从开始状态到结束状态的最短路径。得到的路径即为本题答案。

先从解决长度为3的单词开始。首先定义结果类

class BFSTransformResult:'''状态值组成的图结果类'''def __init__(self):self.level = {}self.parent = {}

接下来写广度优先搜索算法

def bfs_transform(start, end, dic):'''构建状态图,宽度优先搜索算法的变体'''dic.append(end)r = BFSTransformResult()r.parent = {start:None}r.level = {start:0}nexts = [start]while nexts:v1 = nexts.pop(0)neighbor = find_next_state(v1, dic)for v2 in neighbor:if v2 not in r.level:r.level[v2] = r.level[v1] + 1r.parent[v2] = v1nexts.append(v2)return r

其中find_next_state()函数用于寻找和v1相连的点集,其核心在于寻找接下来的状态值(可能有多个)。函数的定义如下:

def find_next_state(state, dic):'''寻找下一个状态(只应用于长度为3的单词)'''next_state = []for each in dic:if each[1:] == state[1:] and each[0] != state[0]:next_state.append(each)if each[::2] == state[::2] and each[1] != state[1]:next_state.append(each)if each[0:2] == state[0:2] and each[2] != state[2]:next_state.append(each)return next_state

至此,两个函数已经能够构建出一个包含了所有合法状态的图,只缺少一个寻找最短路径的算法,下面给出它的实现:

def find_shortest_path(transform, start_state, end_state):'''@param transform: BFSTransformResult对象@param start_sate: 开始状态(单词)@param end_state: 终止状态(单词)寻找从开始状态到终止状态的最短路径'''v_parent_list = [end_state]if end_state != start_state:v_parent = transform.parent[end_state]v_parent_list.append(v_parent)while v_parent != start_state and v_parent != None:v_parent = transform.parent[v_parent]v_parent_list.append(v_parent)return v_parent_list

该算法利用了之前定义的BFSTransformResult类,通过level和parent对每个状态的标记,最终找出一条最短路径。接下来我们测试一遍代码,看看能不能出正确结果。

if __name__ == "__main__": start_state = 'hit'end_state = 'cog'dic = ['hot', 'dot', 'dog', 'lot', 'log']transform = bfs_transform(start_state, end_state, dic)print(' -> '.join(find_shortest_path(transform,start_state, end_state)))# 输出 cog -> dog -> dot -> hot -> hit

怎么输出结果是反的?因为在找最短路径的时候是从后往前找的,不要紧,我们把结果翻转就好了,代码如下:

if __name__ == "__main__": start_state = 'hit'end_state = 'cog'dic = ['hot', 'dot', 'dog', 'lot', 'log']transform = bfs_transform(start_state, end_state, dic)# 将结果翻转print(' -> '.join(find_shortest_path(transform,start_state, end_state)[::-1]))# 输出 hit -> hot -> dot -> dog -> cog

这是单词长度为3的情况,倘若单词字典中的单词长度不一定且开始状态和结束状态的单词长度与字典中单词的长度不一样,这个算法就出问题了。接下来考虑上述情况的解决方案。

现在find_next_state()函数只能解决单词长度为3的问题,为了适应更复杂的情况,应该修改该函数的实现,具体看代码

def find_next_state_wide(state, dic):'''寻找一下个状态(普适)'''next_state = []size = len(state)for each in dic:each_size = len(each)for i in range(size):each_lst = list(each)state_lst = list(state)each_lst[min(i, each_size - 1)], state_lst[i] = '', ''if ''.join(each_lst) == ''.join(state_lst):next_state.append(each)return next_state

注意其中的变量i,它是当前状态下可以变换的字母的下标,比如当前状态为('h', 'o', 't'),则i的取值范围为0~2,同时将当前状态和字典中的任一单词下标为i的字母删除,得到的新两个字符串(一个是当前状态单词变更而来,一个由字典中的单词变换而来)如果相等,则认为这是一种可行状态,将其加入next_state数组。在i所有取值都取完之后即可得到所有的可行状态。

写完普适版本的find_next_state()函数之后,我们需要把单词长度变为4来测试算法正确与否:

if __name__ == "__main__": start_state = 'good'end_state = 'like'dic = ['gooe', 'likk', 'doog', 'looe', 'log', 'lioe', 'like']transform = bfs_transform(start_state, end_state, dic)print(' -> '.join(find_shortest_path(transform,start_state, end_state)[::-1]))# 输出 good -> gooe -> looe -> lioe -> like

结果与预期完全相符,本题的状态机解法告一段落。

【算法设计与分析】图搜索算法的应用相关推荐

  1. 算法设计与分析——蒙特卡罗算法(简单、通俗、易懂)C++

    算法设计与分析--蒙特卡罗算法(简单.通俗.易懂) 虽然都是文字描述,但都是较为通俗的语言,相信你看完应该能理解 在实际应用中会遇到一些问题,不论采用确定性算法还是随机性算法,都无法保证每次能到到正确 ...

  2. 计算机算法设计与分析读后感,算法设计与分析基础经典读后感有感

    <算法设计与分析基础>是一本由Anany levitin著作,清华大学出版社出版的胶版纸图书,本书定价:49.00元,页数:409,特精心从网络上整理的一些读者的读后感,希望对大家能有帮助 ...

  3. 程振波 算法设计与分析_算法设计与分析

    本书按照教育部*制定的计算机科学与技术专业规范的教学大纲编写,努力与国际计算机学科的教学要求接轨.强调 算法 与 数据结构 之间密不可分的联系,因而强调融数据类型与定义在该类型上的运算于一体的抽象数据 ...

  4. 计算机算法设计与分析教学大纲,算法设计与分析的教与学(教学大纲)

    原标题:算法设计与分析的教与学(教学大纲) 课程代码:**** 课程负责人: **** 课程中文名称:算法设计与分析 课程英文名称:Designand Analysis of Algorithms 课 ...

  5. 算法设计与分析 ——插入排序算法与归并排序算法比较

    插入排序算法与归并排序算法比较 实验目的 通过插入排序算法与归并排序算法效率对比体会算法在求解问题中的重要性. 实验内容 分别编写函数实现插入排序算法和归并排序算法: 利用随机函数产生大量数据存入数组 ...

  6. 算法设计与分析_算法设计与分析(第2版)第2章分治策略回顾

    YI时间|外刊|MM-DFW|机器学习系列 点击上方蓝字,关注给你写干货的松子茶 分治策略是通用算法设计技术之一,很多有效的算法是它的特殊实现,顾名思义就是分而治之.一个问题能够用分治法求解的要素是 ...

  7. 算法设计与分析_算法导论(CLRS)骨灰级笔记分享:目录

    倘若你去问一个木匠学徒:你需要什么样的工具进行工作,他可能会回答你:"我只要一把锤子和一个锯".但是如果你去问一个老木工或者是大师级的建筑师,他会告诉你"我需要一些精确的 ...

  8. python 算法设计与分析_算法设计与分析(黄建军)

    spContent=本课基于主讲教师在北京大学讲授数据结构与算法课(Python版)的多年教学实践经验,面向具有Python语言程序设计基础的大学生和社会公众,介绍常见的基本数据结构以及相关经典算法, ...

  9. 算法设计与分析python_Python算法设计与分析

    内容提要 本书内容包括算法初步.排序算法.查找.双指针问题.哈希算法.深度优先搜索算法.广度优先搜索算法.回溯算法.动态规划.贪心算法.分治算法.并查集.最短路径算法和数论算法等常见算法.每个算法都做 ...

  10. 【算法设计与分析】算法的时间复杂度(介绍O渐近上界,Ω渐近下界,θ准确的界)

    什么是时间复杂度? 我们先看看一些函数的渐近表达式: 关于时间复杂度的基本要点: 时间复杂度反映的是随着问题规模的变大,计算所需的时间的增长速度,与系数的多少关系不大 算法的渐近时间复杂度,简称时间复 ...

最新文章

  1. c语言杨辉三角的实现
  2. django-orm操作小结
  3. C#6.0 十大常用特性
  4. Go语言基础进阶—程序结构—类型
  5. 邮件服务器突然很慢,原因探究与处理
  6. c语言随机数 linux,C语言随机数生成教程(rand和srand用法)
  7. 网易云升级服务(云函数)
  8. 百度网盘高速直链提取
  9. 用个人微信小号代替【Server酱】推送消息通知
  10. post测试+php文件,PHPT – 无法运行使用–POST_RAW–的示例测试
  11. 墨天轮国产数据库沙龙 | 胡彦军:华为GaussDB迁移工具解密
  12. wishbone协议(B.3)下载地址
  13. 中学教师资格证——综合素质备考心得+建议
  14. Docker_使用DockerFile监本构建镜像
  15. Android UI 字体库(.ttf文件)的使用 -- xml方式
  16. python:cv2.putText用法
  17. java如何设置例外站点_java添加例外站点
  18. xDSL:数字用户线路技术(DSL、IDSL、ADSL、HDSL、SDSL、VDSL、G.Lite)--网络大典
  19. 1125和855最小公倍数C语言,2016衢州省考行测数量关系送分题:最小公倍数和最大公约数...
  20. 干货 | Tabu Search求解作业车间调度问题(Job Shop Scheduling)-附Java代码

热门文章

  1. CTF密码学解题思路
  2. unity开发 斗地主算法—判断手里的牌是否有大于上家的牌(是否显示要不起按钮)
  3. 完全演示在虚拟机中装Windows7
  4. 尼日利亚4g频段_世界各国全球主要4g频段资料
  5. 编辑中的word变成只读_word只读模式怎么改 word保存文件提示此文件为只读无法保存修改方法...
  6. error ‘for’ loop initial declarations are only allowed in C99 mode的报错原因和两种解决办法
  7. 初识F5之BIGIP-LTM负载均衡
  8. 用 Opencv 和 Python 对汪星人做模糊检测
  9. 脚踩智能汽车春风,百度踏上千亿美元市值征程
  10. ARP缓存表过期问题