【图论】【数据结构】图的深度优先与广度优先遍历、最短路径

用栈实现图的深度优先遍历,队列实现广度优先遍历。

深度优先遍历

#!/usr/bin/python3
import random
import enum
import itertools
import math

Col = enum.Enum("Color", ("White", "Gray", "Black"))


def DFS(G, s):
    visited = set()
    Q = []
    Q.append(s)
    visited.add(s)
    while Q:
        u = Q.pop()
        print(u)
        for i in G[u]:
            if i not in visited:
                Q.append(i)
                visited.add(i)


def BFS(G, s):
    visited = set()
    Q = []
    Q.append(s)
    visited.add(s)
    while Q:
        u = Q.pop(0)
        print(u)
        for i in G[u]:
            if i not in visited:
                Q.append(i)
                visited.add(i)


class Vertex:
    _cnt = 0

    # @staticmethod
    def __init__(self, u, col, pi):
        self._cnt += 1
        self.u = u
        self.col = col
        self.pi = pi
        self.d = math.inf
        self.dt = 0
        self.ft = 0

    @property
    def Count(self):
        return self._cnt

    def __repr__(self):
        # return "Vertex(%s, col %s, perceding %s)" % (self.u, self.col, self.pi)
        return "%s" % self.u


# A* keep with reference book
def ABFS(G, s):
    s.col = Col.Gray
    s.d = 0
    s.pi = None
    Q = []
    Q.append(s)
    while Q:
        u = Q.pop(0)
        for x in G[u]:
            if x.col == Col.White:
                x.col = Col.Gray
                x.d = u.d + 1
                x.pi = u
                Q.append(x)
        u.col = Col.Black


def AShortestPath(G, s, e, path=[]):
    if e == s:
        print(s)
        path.append(s)
        return
    elif e.pi == None:
        print("No path from", s, "to", e)
    else:
        AShortestPath(G, s, e.pi, path)
        print(e)
        path.append(e)


def FindPath(G, s, e, p):
    # [] just for enhancing list +
    p += [s]
    if s == e:
        return p
    for n in G[s]:
        if n not in p:
            np = FindPath(G, n, e, p)
            if np:
                return np
    return None


def findAllPath(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return [path]
    paths = []  # 存储所有路径
    for node in graph[start]:
        if node not in path:
            newpaths = findAllPath(graph, node, end, path)
            for newpath in newpaths:
                paths.append(newpath)
    return paths


def isNotRepeat(all, a):
    for i in all:
        s = set(i)
        sa = set(a)
        if sa.issubset(s):
            return False
    return True


def findMaxClique(graph):
    print("Start")
    clique_set = []
    # 遍历该团的顶点,
    for a in graph.keys():
        #  遍历顶点,对每个顶点查找其相邻顶点,构建初始团
        cli_can = [a, graph[a][random.randrange(0, len(graph[a]))]]
        if isNotRepeat(clique_set, cli_can):
            for i in cli_can:
                # 对其相邻neighbour顶点,若已经在团内的跳过,判断可否加入团,
                nb = graph[i]
                for j in nb:
                    if j in cli_can:
                        continue
                    else:
                        is_memb = True
                        for ii in cli_can:
                            if j not in graph[ii]:
                                is_memb = False
                                break
                        if is_memb:
                            cli_can.append(j)
            clique_set.append(cli_can)
    n_max = 0
    mc = None
    # 比较各个团的大小。
    for c in clique_set:
        num = len(c)
        if num > n_max:
            n_max = num
            mc = c
    return mc


if __name__ == "__main__":
    G = []
    v0 = Vertex("s", Col.White, None)
    v01 = Vertex("r", Col.White, None)
    v02 = Vertex("w", Col.White, None)
    v0.next = v01
    v01.next = v02
    G.append(v0)
    v1 = Vertex("w", Col.White, None)
    v11 = Vertex("s", Col.White, None)
    v12 = Vertex("t", Col.White, None)
    v13 = Vertex("x", Col.White, None)
    v1.next = v11
    v11.next = v12
    v12.next = v13
    G.append(v1)
    print("Broad First Search")
    Ga = {
        # 0
        "r": ["s", "v"],
        # 1
        "s": ["r", "w"],
        # 2
        "t": ["w", "x", "u"],
        # 3
        "u": ["t", "x", "y"],
        # 4
        "v": ["r"],
        # 5
        "w": ["s", "t", "x"],
        # 6
        "x": ["w", "t", "u", "y"],
        # 7
        "y": ["x", "u"],
    }
    BFS(Ga, "s")
    DFS(Ga, "s")
    path = []
    print("FindPath", FindPath(Ga, "s", "y", []))
    graph = {
        "A": ["B", "C", "D"],
        "B": ["E"],
        "C": ["D", "F"],
        "D": ["B", "E", "G"],
        "E": [],
        "F": ["D", "G"],
        "G": ["E"],
    }
    ap = []
    findAllPath(graph, "A", "G", ap)
    alph = "rstuvwxy"
    lv = [Vertex(i, Col.White, Vertex(None, None, None)) for i in itertools.chain(alph)]
    m = dict(zip(alph, range(len(alph))))
    Gb = {}
    for (k, v) in Ga.items():
        key = lv[m[k]]
        Gb[key] = [lv[m[i]] for i in v]
    print(Gb)
    ABFS(Gb, lv[m["s"]])
    path = []
    AShortestPath(Ga, lv[m["s"]], lv[m["u"]], path)
    print(path)

递归方式实现DFS,

import enum
import math

Col = enum.Enum("Color", ("White", "Gray", "Black"))


class Vertex:
    _cnt = 0

    # @staticmethod
    def __init__(self, u, col, pi):
        self._cnt += 1
        self.u = u
        self.col = col
        self.pi = pi
        self.d = math.inf
        self.dt = 0
        self.ft = 0

    @property
    def Count(self):
        return self._cnt

    def __repr__(self):
        # return "Vertex(%s, col %s, perceding %s)" % (self.u, self.col, self.pi)
        return "%s" % self.u


class SolutionDFS:
    def __init__(self):
        self.time = 0

    def ADFS_VISIT(self, G, u):
        self.time += 1
        u.dt = self.time
        u.col = Col.Gray
        for v in G[u]:
            if v.col == Col.White:
                v.pi = u
                self.ADFS_VISIT(G, v)
        u.col = Col.Black
        self.time += 1
        u.ft = self.time

    def ADFS(self, G):
        for v in G.keys():
            v.col = Col.White
            v.pi = None
        self.time = 0
        for v in G.keys():
            if v.col == Col.White:
                self.ADFS_VISIT(G, v)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值