今天在图书馆闲逛的时候偶然看见《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)