【python3数据结构】图Graph及DFS(深度优先搜索)BFS(广度优先搜索)

Graph 和 Vertex 构建基于邻接列表:

# -*- coding: utf-8 -*-
# @Date   : 2019/12/1
# @File   : AdjListGraph.py

import sys

class Vertex(object):

    def __init__(self, node):
        self.id = node
        self.adjacent = {} # 存该节点的邻居及其边权重
        self.distance = sys.maxsize
        self.visited = False
        self.previous = None

    def addNeighbor(self, neighbor, weight=0):
        self.adjacent[neighbor] = weight

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

    def getVertexID(self):
        return self.id

    def setVertexID(self, id):
        self.id = id

    def getWeight(self, neighbor):
        return self.adjacent.get(neighbor)

    def setDistance(self, dist):
        self.distance = dist

    def getDistance(self):
        return self.distance

    def setPrevious(self, prev):
        self.previous = prev

    def setVisited(self):
        self.visited = True

    # 打印节点时显示的信息
    def __str__(self):
        return str(self.id) + " adjacent: " + str([x.id for x in self.adjacent])

    def __lt__(self, other):
        return self.distance < other.distance and self.id < other.id


class Graph(object):

    def __init__(self, directed=False):
        self.vertexDict = {} # key:id  value:Vertex(id)
        self.numVertices = 0
        self.directed = directed

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

    def isDirected(self):
        return self.directed

    def vertexCount(self):
        return self.numVertices

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

    def getVertex(self, n):
        return self.vertexDict.get(n)

    def addEdge(self, frm, to, cost=0):
        if frm not in self.vertexDict:
            self.addVertex(frm)
        if to not in self.vertexDict:
            self.addVertex(to)
        self.vertexDict[frm].addNeighbor(self.vertexDict[to], cost)
        if not self.directed:
            self.vertexDict[to].addNeighbor(self.vertexDict[frm], cost)

    def getVertices(self):
        # return ids
        return self.vertexDict.keys()

    # def setPrevious(self, current):
    #     self.previous = current
    #
    # def getPrevious(self, current):
    #     return self.previous

    def getEdges(self):
        edges = []
        for key, currentVertex in self.vertexDict.items():
            for neighbor in currentVertex.getConnections():
                currentVertexID = currentVertex.getVertexID()
                neighborID = neighbor.getVertexID()
                edges.append((currentVertexID, neighborID, currentVertex.getWeight(neighbor)))
        return edges

    def getNeighbors(self, v):
        vertex = self.vertexDict[v]
        return vertex.getConnections()


if __name__ == '__main__':

    G = Graph(True)
    G.addVertex('a')
    G.addVertex('b')
    G.addVertex('c')
    G.addVertex('d')
    G.addVertex('e')
    G.addVertex('f')
    G.addEdge('a', 'b', 1)
    G.addEdge('a', 'c', 1)
    G.addEdge('b', 'd', 1)
    G.addEdge('b', 'e', 1)
    G.addEdge('c', 'd', 1)
    G.addEdge('c', 'e', 1)
    G.addEdge('d', 'e', 1)
    G.addEdge('e', 'a', 1)
    print(G.getEdges())
    for k in G.getEdges():
        print(k)

    print()
    for key in G.vertexDict:
        # 对应 Vertex中的__str__
     print(key, 'corresponds to', G.vertexDict[key])

    print()

    v = 'a'
    neighbors = G.getNeighbors(v)
    for n in neighbors:
        print(n)

    # 基于边的结合构建图
    def graphFromEdgeList(E, directed=False):
        """Make a graph instance based on a sequence of edge tuples.
            Edges can be either of from (origin,destination) or
            (origin,destination,element). Vertex set is presume to be those
            incident to at least one edge.
            vertex labels are assumed to be hashable.
            """
        g = Graph(directed)
        # 得到所有节点名称
        V = set()
        for e in E:
            V.add(e[0])
            V.add(e[1])
        print("Vertex :", V)
        # 构建图节点vertex
        vertices = {}
        for v in V:
            vertices[v] = g.addVertex(v)
        print(g.vertexCount())
        # 根据边集合为节点添加边
        for e in E:
            src = e[0]
            dest = e[1]
            cost = e[2] if len(e) > 2 else None
            g.addEdge(src, dest, cost)
        return g


    E2 = (
        ('A', 'B', 1), ('A', 'C', 1),
    )
    graph = graphFromEdgeList(E2, True)
    for k in graph.getEdges():
        print(k)

    print()
    E = (
        ('SFO', 'LAX', 337), ('SFO', 'BOS', 2704), ('SFO', 'ORD', 1846),
        ('SFO', 'DFW', 1464), ('LAX', 'DFW', 1235), ('LAX', 'MIA', 2342),
        ('DFW', 'ORD', 802), ('DFW', 'MIA', 1121), ('ORD', 'BOS', 867),
        ('ORD', 'JFK', 740), ('MIA', 'JFK', 1090), ('MIA', 'BOS', 1258),
        ('JFK', 'BOS', 187),
    )
    graph = graphFromEdgeList(E, True)
    for e in graph.getEdges():
        print(e)

    for m in graph.getVertices():
        print(m)

 

 

DFS:

# -*- coding: utf-8 -*-
# @Date   : 2019/12/1
# @File   : DepthFirstSearch.py

from AdjListGraph import Graph, Vertex

def __dfsHelper(s, G, visited, parents):
    # if s == G:
    #     return
    if s not in visited:
        visited[s.getVertexID()] = True
        print("traversal: ", s.getVertexID())
        for neighbor in s.getConnections():
            if neighbor.getVertexID() not in visited:
                parents[neighbor.getVertexID()] = s.getVertexID()
                __dfsHelper(neighbor, G, visited, parents)
        # print(parents)

def DFSRecursive(G):
    visited = {}
    parents = {}
    for node in G:
        if node.getVertexID() not in visited:
            __dfsHelper(node, G, visited, parents)
    print(visited)
    print(parents)




def DFSIterative(G, start, dest):
    stack = []
    parents = {}
    visited = set()
    stack.append(start)
    while stack:
        node = stack.pop()
        print("traversal: ", node.getVertexID())

        if node.getVertexID() == dest.getVertexID():
            return parents

        # if node not in visited:
        visited.add(node.getVertexID())
        for neighbor in G.getNeighbors(node.getVertexID()):
            if neighbor not in visited:
                stack.append(neighbor)
                parents[neighbor.getVertexID()] = node.getVertexID()
    return None



if __name__ == '__main__':

    G = Graph(directed=True)
    G.addVertex('a')
    G.addVertex('b')
    G.addVertex('c')
    G.addVertex('d')
    G.addVertex('e')
    G.addVertex('f')
    G.addEdge('a', 'b', 1)
    G.addEdge('a', 'c', 1)
    G.addEdge('b', 'd', 1)
    G.addEdge('b', 'e', 1)
    G.addEdge('c', 'd', 1)
    G.addEdge('c', 'e', 1)
    G.addEdge('d', 'e', 1)
    G.addEdge('e', 'a', 1)
    G.addEdge('a', 'f', 1)
    print(G.getEdges())
    for k in G.getEdges():
        print(k)

    visited = {}
    parents = {}
    DFSRecursive(G)
    print()
    # 从v节点开始遍历
    v = G.getVertex('e')
    __dfsHelper(v, G, visited, parents)

    #
    print("#"*20)
    start = G.getVertex('a')
    dest = G.getVertex('e')
    print(DFSIterative(G, start=start, dest=dest))

 

BFS:

# -*- coding: utf-8 -*-
# @Date   : 2019/12/1
# @File   : BreadthFirstSearch.py

from AdjListGraph import Graph
from collections import deque


def BFSIterative(G, start, dest):
    queue = deque()
    visited = set()
    parents = {}
    queue.append(start)
    while queue:
        node = queue.popleft()
        print("visiting :", node.getVertexID())
        if node.getVertexID() == dest.getVertexID():
            return parents
        visited.add(node.getVertexID())
        for neighbor in G.getNeighbors(node.getVertexID()):
            if neighbor not in visited:
                queue.append(neighbor)
                parents[neighbor.getVertexID()] = node.getVertexID()
    return None



if __name__ == '__main__':
    G = Graph(directed=True)
    G.addVertex('a')
    G.addVertex('b')
    G.addVertex('c')
    G.addVertex('d')
    G.addVertex('e')
    G.addVertex('f')
    G.addEdge('a', 'b', 1)
    G.addEdge('a', 'c', 1)
    G.addEdge('a', 'f', 1)
    G.addEdge('b', 'd', 1)
    G.addEdge('b', 'e', 1)
    G.addEdge('c', 'd', 1)
    G.addEdge('c', 'e', 1)
    G.addEdge('d', 'e', 1)
    G.addEdge('e', 'a', 1)

    print(G.getEdges())
    for k in G.getEdges():
        print(k)

        #
    print("#" * 20)
    start = G.getVertex('a')
    dest = G.getVertex('e')
    print(BFSIterative(G, start=start, dest=dest))

DFS vs BFS:

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值