zoukankan      html  css  js  c++  java
  • <Think Complexity> 用字典实现图

    今天在图书馆闲逛的时候偶然看见《Think Complexity》(复杂性思考)这本书,下午看了一会儿觉得很有意思。本书第二章讲的是用Python实现的图,特别写篇博客记录。

    首先,图有两大元素:顶点和边。分别用Vertex和Edge类来描述顶点集和边集。

    顶点集:Vertex

    class Vertex(object):
        """A Vertex is a node in a graph."""
    
        def __init__(self, label=''):
            self.label = label
    
        def __repr__(self):
            """Returns a string representation of this object that can
            be evaluated as a Python expression."""
            return 'Vertex(%s)' % repr(self.label)
    
        __str__ = __repr__
        """The str and repr forms of this object are the same."""

    边集:Edge

    class Edge(tuple):
        """An Edge is a list of two vertices."""
    
        def __new__(cls, *vs):
            """The Edge constructor takes two vertices."""
            if len(vs) != 2:
                raise ValueError, 'Edges must connect exactly two vertices.'
            return tuple.__new__(cls, vs)
    
        def __repr__(self):
            """Return a string representation of this object that can
            be evaluated as a Python expression."""
            return 'Edge(%s, %s)' % (repr(self[0]), repr(self[1]))
    
        __str__ = __repr__
        """The str and repr forms of this object are the same."""

    可以看出,边集类实现时继承的是元组,是不可变的对象,其初始化方法重写了__new__()方法。在构造类时,Python会调用__new__()方法创建对象,再调用__init__()方法初始化对象属性,对于可变类型来讲,一般做法是使用默认的__new__()方法,而重写__init__()方法来初始化属性;然而对于不可变类型来说(如元组),__init__()方法不能改变其属性值,因为必须重写__new__()方法来进行初始化。

    如今图的边和点都有了,现在进行图的构造:

    class Graph(dict):
        """A Graph is a dictionary of dictionaries.  The outer
        dictionary maps from a vertex to an inner dictionary.
        The inner dictionary maps from other vertices to edges.
        
        For vertices a and b, graph[a][b] maps
        to the edge that connects a->b, if it exists."""
    
        def __init__(self, vs=[], es=[]):    #初始化
            """Creates a new graph.  
            vs: list of vertices;
            es: list of edges.
            """
            for v in vs:
                self.add_vertex(v)
                
            for e in es:
                self.add_edge(e)
    
        def add_vertex(self, v):            #将点添加至图
            """Add a vertex to the graph."""
            self[v] = {}
    
        def add_edge(self, e):                #添加边,不考虑重边
            """Adds and edge to the graph by adding an entry in both directions.
    
            If there is already an edge connecting these Vertices, the
            new edge replaces it.
            """
            v, w = e
            self[v][w] = e
            self[w][v] = e
    
        def get_edge(self, v1, v2):            #返回两点之间的边,若无边返回None
            
            try:
                return self[v1][v2]
            except:
                return None
    
        def remove_edge(self, e):            #去掉边
    
            v, w = e
            del self[v][w]
            del self[w][v]
    
        def vertices(self):                    #返回点集
            
            return [each for each in self]
    
        def edges(self):                    #返回边集
            edges_list = []
            for each in self.values():
                for each_value in each.values():
                    if each_value not in edges_list:
                        edges_list.append(each_value)
    
            return edges_list
    
        def out_vertices(self, v):            #返回邻接顶点
            nebor = [each for each in self[v]]
            return nebor
                      
        def out_edges(self, v):                #返回与顶点连接的边
            return [each for each in self[v].values()]
            
        def add_all_edges(self):            #构造完全图
            edges = []
            for v in self:
                for w in self:
                    if v != w:
                        e = Edge(v,w)
                        self.add_edge(e)
    这样,图的结构和基本操作就完成了。
  • 相关阅读:
    《Linux shell变量总结回顾》RHEL6(转)
    20个最受欢迎的Linux命令(转)
    如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧(转)
    妻共贫贱难,夫共富贵难
    [置顶] 阅读Oracle官方文档指南
    Java实现 蓝桥杯 算法训练 递归求二项式系数
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
  • 原文地址:https://www.cnblogs.com/jaletech/p/3587223.html
Copyright © 2011-2022 走看看