【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS
词梯Word Ladder问题
- 要求是相邻两个单词之间差异只能是1个字母,如FOOL变SAGE:
FOOL >> POOL >> POLL >> POLE >> PALE>> SALE >> SAGE
- 目标是找到最短的单词变换序列
- 用图表示单词之间的关系;
- 用一种名为
广度优先搜索 BFS
的图算法找到从起始单词到结束单词的最短路径。
构建词梯图
算法
- 首先是将所有单词作为顶点加入图中,再设法建立顶点之间的边
- 对每个顶点(单词) , 与其它所有单词进行比较, 如果相差仅1个字母, 则建立一条边
- 时间复杂度是O(n²),对于所有4个字母的5110个单词,需要超过2600万次比较
优化算法
- 改进的算法是创建大量的桶, 每个桶可以存放若干单词
- 桶标记是去掉1个字母,通配符“_”占空的单词
- 所有匹配标记的单词都放到这个桶里
- 所有单词就位后,再在同一个桶的单词之间建立边即可
- 单词关系图是一个非常稀疏的图
采用字典建立桶
def buildGraph(wordFile):
d = {}
g = Graph()
wfile = open(wordFile, 'r')
for line in wfile:
word = line[:-1]
for i in range(len(word)):
bucket = word[:i]+'_'+[i+1:]
if bucket in d:
d[bucket].append(word)
else:
d[bucket] = [word]
for bucket in d.keys():
for word1 in d[bucket]:
for word2 in d[bucket]:
if word1 != word2:
g.addEdge(word1, word2)
return g
广度优先搜索 BFS (breadth first search)
在单词关系图建立完成以后, 需要继续在图中寻找词梯问题的最短序列
算法思路
- 给定图G, 以及开始搜索的起始顶点s
- BFS搜索所有从s可到达顶点的边
- 而且在达到更远的距离k+1的顶点之前, BFS会找到全部距离为k的顶点
- 可以想象为以s为根,构建一棵树的过程,从顶部向下逐步增加层次
- 广度优先搜索能保证在增加层次之前,添加了所有兄弟节点到树中
- 为了跟踪顶点的加入过程, 并避免重复顶点, 要为顶点增加3个属性
- 距离distance:从起始顶点到此顶点路径长度;
- 前驱顶点predecessor:可反向追溯到起点;
- 颜色color:
- 标识了此顶点是尚未发现(白色)
- 已经发现(灰色)
- 还是已经完成探索(黑色)
- 还需要用一个队列Queue来对已发现的顶点进行排列
决定下一个要探索的顶点(队首顶点)
算法过程
从起始顶点s开始, 作为刚发现的顶点,标注为灰色, 距离为0, 前驱为None,加入队列, 接下来是个循环迭代过程:
- 从队首取出一个顶点作为当前顶点;
- 遍历当前顶点的邻接顶点,如果是尚未发现的白色顶点,则将其颜色改为灰色(已发现),距离增加1,前驱顶点为当前顶点,加入到队列中
- 遍历完成后,将当前顶点设置为黑色(已探索过),循环回到步骤1的队首取当前顶点
代码
- 在以FOOL为起始顶点, 遍历了所有顶点, 并为每个顶点着色、 赋距离和前驱的代码
def bfs(g, start):
start.setDistance(0)
start.setPred(None)
vertQueue = Queue()
vertQueue.enqueue(start)
while(vertQueue.size > 0):
currentVert = vertQueue.dequeue()
for nbr in currentVert.getConnections():
if(nbr.getColor() == 'white'):
nbr.setColor('gray')
nbr.setDistance(currentVert.getDistance()+1)
nbr.setPred(currentVert)
vertQueue.enqueue(nbr)
currentVert.setColor('black')
- 最后,通过一个回途追溯函数来确定FOOL到任何单词顶点的最短词梯!
def traverse(y):
x = y
while(x.getPred()):
print(x.getId())
x = x.getPred()
print(x.getId())
完整代码
def buildGraph(wordFile):
d = {}
g = Graph()
wfile = open(wordFile, 'r')
for line in wfile:
word = line[:-1]
for i in range(len(word)):
bucket = word[:i]+'_'+[i+1:]
if bucket in d:
d[bucket].append(word)
else:
d[bucket] = [word]
for bucket in d.keys():
for word1 in d[bucket]:
for word2 in d[bucket]:
if word1 != word2:
g.addEdge(word1, word2)
return g
def bfs(g, start):
start.setDistance(0)
start.setPred(None)
vertQueue = Queue()
vertQueue.enqueue(start)
while(vertQueue.size > 0):
currentVert = vertQueue.dequeue()
for nbr in currentVert.getConnections():
if(nbr.getColor() == 'white'):
nbr.setColor('gray')
nbr.setDistance(currentVert.getDistance()+1)
nbr.setPred(currentVert)
vertQueue.enqueue(nbr)
currentVert.setColor('black')
def traverse(y):
x = y
while(x.getPred()):
print(x.getId())
x = x.getPred()
print(x.getId())
if __name__ == "__main__":
wordgrah = buildGraph("fourletterwords.txt")
bfs(wordgrah, wordgrah.getVertex('FOOL'))
traverse(wordgrah.getVertex('SAGE'))
算法分析
- BFS算法主体是两个循环的嵌套
- while循环对每个顶点访问一次,所以是O(|V|)
- 而嵌套在while中的for,由于每条边只有在其起始顶点u出队的时候才会被检查一次
- 而每个顶点最多出队1次,所以边最多被检查1次,一共是O(|E|)
- 综合起来BFS的时间复杂度为O(|V|+|E|)
- 词梯问题还包括两个部分算法
- 建立BFS树之后, 回溯顶点到起始顶点的过程,最多为O(|V|)
- 创建单词关系图也需要时间,最多为O(|V|2)
【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS的更多相关文章
- 【数据结构与算法Python版学习笔记】目录索引
引言 算法分析 基本数据结构 概览 栈 stack 队列 Queue 双端队列 Deque 列表 List,链表实现 递归(Recursion) 定义及应用:分形树.谢尔宾斯基三角.汉诺塔.迷宫 优化 ...
- 【数据结构与算法Python版学习笔记】引言
学习来源 北京大学-数据结构与算法Python版 目标 了解计算机科学.程序设计和问题解决的基本概念 计算机科学是对问题本身.问题的解决.以及问题求解过程中得出的解决方案的研究.面对一 个特定问题,计 ...
- 【数据结构与算法Python版学习笔记】图——最短路径问题、最小生成树
最短路径问题 概念 可以通过"traceroute"命令来跟踪信息传送的路径: traceroute www.lib.pku.edu.cn 可以将互联网路由器体系表示为一个带权边的 ...
- 【数据结构与算法Python版学习笔记】图——强连通分支
互联网 我们关注一下互联网相关的非常巨大图: 由主机通过网线(或无线)连接而形成的图: 以及由网页通过超链接连接而形成的图. 网页形成的图 以网页(URI作为id)为顶点,网页内包含的超链接作为边,可 ...
- 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索
骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...
- 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort
概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...
- 【数据结构与算法Python版学习笔记】图——基本概念及相关术语
概念 图Graph是比树更为一般的结构, 也是由节点和边构成 实际上树是一种具有特殊性质的图 图可以用来表示现实世界中很多有意思的事物,包括道路系统.城市之间的航班.互联网的连接,甚至是计算机专业的一 ...
- 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链
散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...
- 【数据结构与算法Python版学习笔记】算法分析
什么是算法分析 算法是问题解决的通用的分步的指令的聚合 算法分析主要就是从计算资源的消耗的角度来评判和比较算法. 计算资源指标 存储空间或内存 执行时间 影响算法运行时间的其他因素 分为最好.最差和平 ...
随机推荐
- kubeadm方式搭建K8S集群
一.kubeadm介绍 二.安装要求 三.集群规划 四.环境初始化(在每个服务器节点操作) 1.关闭防火墙 2.关闭selinux 3.关闭swap 4.根据规划设置主机名 5.在Master添加ho ...
- matlab纹理映射之地球
%地球 cla reset; load topo; [x,y,z] = sphere(45); s = surface(x,y,z,'facecolor','texturemap','cdata',t ...
- 第09课:GDB 实用调试技巧(下)
本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...
- word文档转成图片
1:先把word文档转成pdf格式 这个是在word中转成pdf格式,保存好 2:再把pdf格式转成图片 在这个链接中打开https://smallpdf.com/cn/pdf-converter, ...
- 地址栏url中去掉所有参数
1.地址栏url中去掉所有参数,这个是纯前端解决,很多时候页面跳转时候会选择在url后面带参数过去,(使用?&),方便传也方便取,但是我们要做的是不要让页面的一些请求参数暴露在外面 正常项目工 ...
- python多继承简单方法
class people(object): #建创一个人类 def __init__(self,name,age): self.name = name self.age = age def eat(s ...
- 【Sass/SCSS 完整自学中文版教程01】SCSS 官方英文文档翻译整理
Sass 基本介绍 目录 Sass 基本介绍 注释(Comments) 单行注释(Single-line comments) 多行注释(Multi-line comments) SassDoc 特殊的 ...
- CentOS安装oh-my-zsh并配置语法高亮和命令自动补全
安装zsh 和 oh-my-zsh 安装zsh yum install zsh 安装git yum install git 切换默认shell chsh -s /bin/zsh clone from ...
- 论文解读(DGI)《DEEP GRAPH INFOMAX》
论文标题:DEEP GRAPH INFOMAX 论文方向:图像领域 论文来源:2019 ICLR 论文链接:https://arxiv.org/abs/1809.10341 论文代码:https:// ...
- DS博客作业04--图
这个作业属于哪个班级 数据结构--网络2011/2012 这个作业的地址 DS博客作业04--图 这个作业的目标 学习图结构设计及相关算法 姓名 黄静 目录 0.PTA得分截图 1.本周学习总结 1. ...