python 图 遍历-深度优先和广度优先 II

在上一篇(python 图 遍历-深度优先和广度优先)的代码上加了最小生成树和拓扑序列功能。代码如下:

#!/usr/bin/env python
#-*- coding:utf8 -*-
import copy

class Graph(object):

    def __init__(self, *args, **kwargs):
        self.node_neighbors = {}
        self.visited = {}
        self.edge_properties = {}  #记录边的权重
        self.in_degree = {}  # 入度

    def add_nodes(self, nodelist):
        for node in nodelist:
            self.add_node(node)

    def add_node(self, node):
        if not node in self.node_neighbors:
            self.node_neighbors[node] = []

    def add_edge(self, edge, weight=1):
        u, v = edge
        if (v not in self.node_neighbors[u]) and (u not in self.node_neighbors[v]):
            self.node_neighbors[u].append(v)
            if (u != v):
                self.node_neighbors[v].append(u)
                self.edge_properties[edge] = weight
                self.edge_properties[(v, u)] = weight

    def add_arc(self, edge, weight=1):

        “”” 加弧,有向”””
        u, v = edge
        if v not in self.node_neighbors[u]:
            self.node_neighbors[u].append(v)
            self.edge_properties[edge] = weight
            if v in self.in_degree:
                self.in_degree[v] = self.in_degree[v] + 1
            else:
                self.in_degree[v] = 1
            if u not in self.in_degree:
                self.in_degree[u] = 0

    def edge_weight(self, edge):
        if edge in self.edge_properties:
            return self.edge_properties[edge]
        return -1

    def nodes(self):
        return self.node_neighbors.keys()

    def depth_first_search(self, root=None):
        order = []
        def dfs(node):
            self.visited[node] = True
            order.append(node)
            for n in self.node_neighbors[node]:
                if not n in  self.visited:
                    dfs(n)
        if root:
            dfs(root)
        for node in self.nodes():
            if not node in self.visited:
                dfs(node)
        print order
        return order

    def breadth_first_search(self, root=None):
        queue = []
        order = []
        def bfs():
            while len(queue) > 0:
                node = queue.pop(0)
                self.visited[node] = True
                for n in self.node_neighbors[node]:
                    if (not n in self.visited) and (not n in queue):
                        queue.append(n)
                        order.append(n)
        if root:
            queue.append(root)
            order.append(root)
            bfs()
        for node in self.nodes():
            if not node in self.visited:
                queue.append(node)
                order.append(node)
                bfs()
        print order
        return order

    def prim_min_tree(self, root=None):
        “””最小生成树:普里姆算法”””
        spanning_tree = {}

        def light_edge():
            min_weight = 10000
            edge = None
            for node in self.visited.keys():
                for other in self.node_neighbors[node]:
                    if not other in self.visited:
                        if self.edge_weight((node, other)) != -1 and self.edge_weight((node, other)) < min_weight:
                            min_weight = self.edge_weight((node, other))
                            edge = (node, other)
            return edge, min_weight

        def get_unvisited_node():
            for node in self.nodes():
                if not node in self.visited:
                    return node

        while len(self.visited.keys()) != len(self.nodes()):
            edge, min_weight = light_edge()
            if edge:
                spanning_tree[(edge[0], edge[1])] = min_weight
                self.visited[edge[1]] = True
            else:
                node = root if root else get_unvisited_node()
                if node:
                    self.visited[node] = True
        return spanning_tree

    def topological_sorting(self):
        “””拓扑序列的逆序列:找到入度为0的,取出,删除以Ta为开始的边,重复这样操作”””
        in_degree = copy.deepcopy(self.in_degree)
        order = []

        def find_zero_in_degree_node():
            for k, v in in_degree.iteritems():
                if v == 0 and (not k in self.visited):
                    return k
            return None

        def do(node):
            self.visited[node] = True
            order.append(node)
            for other in self.node_neighbors[node]:
                if other not in self.visited:
                    in_degree[other] -= 1

        node = find_zero_in_degree_node()
        while node:
            do(node)
            node = find_zero_in_degree_node()
        if len(order) == len(self.nodes()):
            return order
        return None  # 有回环,没有拓扑序列

    def shortest_path(self, source):
        “””最短路径Dijkstra’s algorithm:O(n2)”””
        dist = {source: 0}  # 记录最终值
        q = [(0, source)]  # 记录source到点的距离
        while len(q) > 0:
            du, node = q.pop(0)
            self.visited[node] = True
            for n in self.node_neighbors[node]:
                if not n in self.visited:  # 如果还没有访问
                    alt = du + self.edge_properties[(node, n)]
                    if (not n in dist) or alt < dist[n]:
                        dist[n] = alt
                        bisect.insort(q, (alt, n))
        return dist  #返回source到点的距离(如果不能到点,则没有值)

if __name__ == ‘__main__’:

    g = Graph()
    g.add_nodes([i+1 for i in range(6)])
    g.add_edge((1, 2), 6)
    g.add_edge((1, 3), 1)
    g.add_edge((1, 4), 5)
    g.add_edge((2, 3), 3)
    g.add_edge((2, 5), 5)
    g.add_edge((3, 4), 5)
    g.add_edge((3, 5), 6)
    g.add_edge((3, 6), 4)
    g.add_edge((4, 6), 2)
    g.add_edge((5, 6), 6)
    
    #print “nodes:”, g.nodes()
    #order = g.depth_first_search(1)
    #order = g.breadth_first_search(1)
    #print “breadth_first_search”, order, spanning_tree
    print “最小生成树”, g.prim_min_tree(1)
    g2 = Graph()
    g2.add_nodes([i+1 for i in range(6)])
    g2.add_arc((1, 2))
    g2.add_arc((1, 3))
    g2.add_arc((1, 4))
    g2.add_arc((3, 2))
    g2.add_arc((3, 5))
    g2.add_arc((6, 5))
    g2.add_arc((6, 4))
    g2.add_arc((4, 5))
    print “topological_sorting:”, g2.topological_sorting()

    g3 = Graph()
    g3.add_nodes([i for i in range(6)])
    g3.add_arc((0, 2), 10)
    g3.add_arc((0, 4), 30)
    g3.add_arc((0, 5), 100)
    g3.add_arc((1, 2), 5)
    g3.add_arc((2, 3), 50)
    g3.add_arc((3, 5), 10)
    g3.add_arc((4, 3), 20)
    g3.add_arc((4, 5), 60)
    print “最短路径(到哪个点,距离):”,g3.shortest_path(0)

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/zhujunxxxxx/article/details/28429685
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞