7.2Graph的实现

2019-12-26  本文已影响0人  M_小七

Python 中,通过字典可以轻松地实现邻接表。我们要创建两个类:Graph 类存储包含所
有顶点的主列表,Vertex 类表示图中的每一个顶点。
Vertex 使用字典 connectedTo 来记录与其相连的顶点,以及每一条边的权重。
addNeighbor 方法添加从一个顶点到另一个的连接。getConnections 方法返
回邻接表中的所有顶点,由 connectedTo 来表示。getWeight 方法返回从当前顶点到以参数
传入的顶点之间的边的权重。

class Vertex:
    def __init__(self, key):
        self.id = key
        self.connectedTo = {}

    def addNeighbor(self, nbr, weight=0):
        self.connevtedTo[nbr] = weight

    def __str__(self):
        return str(self.id) + 'connectedTo:' + str([x.id for x in self.connectedTo])

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self, nbr):
        return  self.connectedTo[nbr]


Graph 类中包含一个将顶点名映射到顶点对象的字典。Graph 类也提供了向图中添加顶点和连接不同顶点的方法。getVertices 方法返回图中所有顶点的名字。iter方法,使遍历图中的所有顶点对象更加方便。

class Graph:
    def __init__(self):
        self.vertList = {}
        self.numVertices = 0

    def addVertex(self, key):
        self.numVertices = self.numVertices + 1
        newVertex = Vertex(key)
        self.vertList[key] = newVertex
        return newVertex

    def getVertex(self, n ):
        if n in self.vertList:
            return self.vertList[n]
        else:
            return None

    def __contains__(self, n):
        return n in self.vertList

    def addEdge(self, f, t, cost = 0):
        if f not in self.vertList:
            nv = self.addEdge(f)
        if t not in self.vertList:
            nv = self.addVertex(t)
        self.vertList[f].addNeighbor(self.vertList[t], cost)

    def getVertices(self):
        return self.vertList.keys()

    def __iter__(self):
        return iter(self.vertList.values())


图的应用:词梯问题

词梯Word Ladder问题
由 “ 爱丽丝漫游奇境 ” 的作者 LewisCarroll在1878年所发明的单词游戏
从一个单词演变到另一个单词,其中的过程可以经过多个中间单词。要求是相邻两个单词之间差异只能是1个字母, 如FOOL变SAGE:
FOOL >> POOL >> POLL >> POLE >> PALE >> SALE >> SAGE
目标是找到最短的单词变换序列
采用图来解决这个问题的步骤如下:
将可能的单词之间的演变关系表达为图,采用“广度优先搜索 BFS”,来搜寻从开始单词
到结束单词之间的所有有效路径,选择其中最快到达目标单词的路径

构建单词关系图
❖首先是如何将大量的单词集放到图中
将单词作为顶点的标识Key,如果两个单词之间仅相差1个字母,就在它们之间设一条边
❖从FOOL到SAGE的词梯解,所用的图是无向图,边没有权重
FOOL到SAGE的每条路径都是一个解


image.png

❖单词关系图可以通过不同的算法来构建(以4个字母的单词表为例)
首先是将所有单词作为顶点加入图中,再设法建立顶点之间的边
❖建立边的最直接算法,是对每个顶点(单 词),与其它所有单词进行比较,如果相差仅1个字母,则建立一条边
时间复杂度是O(n^2),对于所有4个字母的5110个单词,需要超过2600万次比较
❖改进的算法是创建大量的桶,每个桶可以存放若干单词
桶标记是去掉1个字母,通配符“_”占空的单词
❖所有匹配标记的单词都放到这个桶里
所有单词就位后,再在同一个桶的单词之间建立边即可


image.png
采用字典建立桶
def buildGraph(file):
    d = {}
    g = Graph()

    #创建词桶
    f = open(file)
    for line in f:
        word = line[:-1]
        # bird
        for i in range(len(word)):
            bucket = word[:i] + '_' + word[i+1:]
            if bucket in d:
                d[bucket].append(word)
            else:
                d[bucket] = [word]
    #构建图
    for bucket in d.keys():
        for v1 in d[bucket]:
            for v2 in d[bucket]:
                if v1 != v2:
                    g.addEdge(v1,v2)
    return g
if __name__ == '__main__':
    g = buildGraph('ds_tree/fourletterwords.txt')
    for item in g.verList.values():
        print(item)
上一篇 下一篇

猜你喜欢

热点阅读