【算法——Python实现】无权图(稠密图、稀疏图)及图的遍历

来源:互联网 发布:仙逆和凡人知乎 编辑:程序博客网 时间:2024/06/11 10:32
# _*_ encoding:utf-8 _*_"""图"""from random import randintimport timeimport copyimport Queueclass DenseGraph(object):    """稠密图 - 邻接矩阵"""    def __init__(self, n, directed):        self.n = n  # 图中的点数        self.m = 0  # 图中的边数        self.directed = directed  # bool值,表示是否为有向图        self.g = [[False for _ in range(n)] for _ in range(n)]  # 矩阵初始化都为False的二维矩阵    def V(self):        # 返回图中点数        return self.n    def E(self):        # 返回图中边数        return self.m    def addEdge(self, v, w):        # v和w中增加一条边,v和w都是[0,n-1]区间        if v >= 0 and v < n and w >= 0 and w < n:            if self.hasEdge(v, w):                return None            self.g[v][w] = True            if not self.directed:                self.g[w][v] = True            self.m += 1    def hasEdge(self, v, w):        # v和w之间是否有边,v和w都是[0,n-1]区间        if v >= 0 and v < n and w >= 0 and w < n:            return self.g[v][w]    class adjIterator(object):        """相邻节点迭代器"""        def __init__(self, graph, v):            self.G = graph  # 需要遍历的图            self.v = v  # 遍历v节点相邻的边            self.index = 0  # 遍历的索引        def __iter__(self):            return self        def next(self):            while self.index < self.G.V():                # 当索引小于节点数量时遍历,否则为遍历完成,停止迭代                if self.G.g[self.v][self.index]:                    r = self.index                    self.index += 1                    return r                self.index += 1            raise StopIteration()class SparseGraph(object):    """稀疏图- 邻接表"""    def __init__(self, n, directed):        self.n = n  # 图中的点数        self.m = 0  # 图中的边数        self.directed = directed  # bool值,表示是否为有向图        self.g = [[] for _ in range(n)]  # 矩阵初始化都为空的二维矩阵    def V(self):        # 返回图中点数        return self.n    def E(self):        # 返回图中边数        return self.m    def addEdge(self, v, w):        # v和w中增加一条边,v和w都是[0,n-1]区间        if v >= 0 and v < n and w >= 0 and w < n:            # 考虑到平行边会让时间复杂度变为最差为O(n)            # if self.hasEdge(v, w):            #   return None            self.g[v].append(w)            if v != w and not self.directed:                self.g[w].append(v)            self.m += 1    def hasEdge(self, v, w):        # v和w之间是否有边,v和w都是[0,n-1]区间        # 时间复杂度最差为O(n)        if v >= 0 and v < n and w >= 0 and w < n:            # for i in self.g[v]:            #   if i == w:            #       return True            # return False            if w in self.g[v]:                return True            else:                return False    class adjIterator(object):        """相邻节点迭代器"""        def __init__(self, graph, v):            self.G = graph  # 需要遍历的图            self.v = v  # 遍历v节点相邻的边            self.index = 0  # 遍历的索引        def __iter__(self):            return self        def next(self):            if len(self.G.g[self.v]):                # v有相邻节点才遍历                if self.index < len(self.G.g[self.v]):                    r = self.G.g[self.v][self.index]                    self.index += 1                    return r                else:                    raise StopIteration()            else:                raise StopIteration()class ReadGraph(object):    """读取文件中的图"""    def __init__(self, graph, filename):        with open(filename, 'r') as f:            line = f.readline()            v, e = self.stringstream(line)            if v == graph.V():                lines = f.readlines()                for i in lines:                    a,b = self.stringstream(i)                    if a >= 0 and a < v and b >=0 and b < v:                        graph.addEdge(a, b)    def stringstream(self, text):        result = text.strip('\n')        result = result.split()        a, b = result        return int(a), int(b)class Component(object):    """深度优先遍历和联通分量"""    def __init__(self, graph):        self.G = graph  # 图        self.ccount = 0  # 联通分量        self.visited = [False for _ in range(self.G.V())]  # 记录每个节点是否被遍历        self.id = [-1 for _ in range(self.G.V())]  # 相连节点的id相同,初始都为-1        i = 0        while i < self.G.V():            if not self.visited[i]:                self.dfs(i)                self.ccount += 1            i += 1    def dfs(self, v):        # 深度优先遍历        self.visited[v] = True        self.id[v] = self.ccount        adj = self.G.adjIterator(self.G, v)  # 找到v节点所有相邻的点,进行迭代遍历        for i in adj:            # 如果遍历到还未遍历的节点,继续向下进行递归的深度遍历            if not self.visited[i]:                self.dfs(i)    def count(self):        # 返回联通分量        return self.ccount    def isConnected(self, v, w):        # 判断节点是否相连        if v >=0 and v < self.G.V() and w >= 0 and w < self.G.V():            return self.id[v] == self.id[w]class Path(object):    """寻找路径"""    def __init__(self, graph, s):        self.G = graph  # 图        self.s = s  # 从s节点开始寻找到其他节点的路径        self.visited = [False for _ in range(self.G.V())]  # 记录每个节点是否被遍历        self.fromed = [-1 for _ in range(self.G.V())] # 记录此节点来自哪个节点的连接        # 寻找路径        self.dfs(s)    def dfs(self, v):        # 深度优先遍历        self.visited[v] = True        adj = self.G.adjIterator(self.G, v)  # 找到v节点所有相邻的点,进行迭代遍历        for i in adj:            # 如果遍历到还未遍历的节点,继续向下进行递归的深度遍历            if not self.visited[i]:                self.fromed[i] = v  # 对还未遍历的节点,先将此节点的from修改为v,表示i节点来自v节点相连                self.dfs(i)    def hasPath(self, w):        # w与v是否有路径        if w >= 0 and w < self.G.V():            return self.visited[w]    def path(self, w):        # 从v到w的路径        s = []        p = w        while p != -1:            s.append(p)            p = self.fromed[p]        s.reverse()        return s    def showPath(self, w):        # 展示路径        s = self.path(w)        for i in s:            print iclass ShortestPath(object):    """广度优先遍历和最短路径"""    def __init__(self, graph, s):        self.G = graph  # 图        self.s = s  # 从s节点开始寻找到其他节点的路径        self.visited = [False for _ in range(self.G.V())]  # 记录每个节点是否被插入队列        self.fromed = [-1 for _ in range(self.G.V())] # 记录此节点来自哪个节点的连接        self.ord = [-1 for _ in range(self.G.V())]  # 记录s节点到每一个节点的距离        # 无向图最短路径算法        q = Queue.Queue()        q.put(s)        self.visited[s] = True        self.ord[s] = 0        while not q.empty():            v = q.get()            adj = self.G.adjIterator(self.G, v)  # 找到v节点所有相邻的点,进行迭代遍历            for i in adj:                # 如果遍历到还未加入过队列的节点,将其加入队列                if not self.visited[i]:                    q.put(i)                    self.visited[i] = True                    self.fromed[i] = v                    self.ord[i] = self.ord[v] + 1    def hasPath(self, w):        # w与v是否有路径        if w >= 0 and w < self.G.V():            return self.visited[w]    def path(self, w):        # 从v到w的路径        s = []        p = w        while p != -1:            s.append(p)            p = self.fromed[p]        s.reverse()        return s    def showPath(self, w):        # 展示路径        s = self.path(w)        for i in s:            print i    def length(self, w):        # s到w的距离        if w >= 0 and w < self.G.V():            return self.ord[w]if __name__=="__main__":    n = 13    g1 = DenseGraph(n, False)    # for _ in range(100):    #   a = randint(0,n-1)    #   b = randint(0,n-1)    #   g1.addEdge(a, b)    # v = 0    # adj = DenseGraph.adjIterator(g1, v)    # for w in adj:    #   print w    filename = 'graph.txt'    readgraph1 = ReadGraph(g1, filename)    # component1 = Component(g1)    # print component1.count()    path1 = Path(g1, 0)    print path1.path(8)    path1.showPath(8)
阅读全文
0 0
原创粉丝点击