<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)
这样,图的结构和基本操作就完成了。
posted @ 2014-03-07 21:33  野风鼓瑟震山岗  阅读(229)  评论(0编辑  收藏  举报