图结构相关的算法

图结构

图由节点和边组成,包括有向图和无向图。
节点的构成:节点值、入度、出度、连接的边、邻居节点。
边的构成:出发节点、到达节点、节点。

class Node:
    """
    节点结构
    """
    def __init__(self, value: int):
        self.value = value
        self.in_degree = 0
        self.out_degree = 0
        self.next_nodes = []
        self.edges = []

class Edge:
    """
    边结构
    """
    def __init__(self, weight: int, src: Node, dst: Node):
        self.weight = weight
        self.src = src
        self.dst = dst

    def __lt__(self, other):
        """
        相当于比较器,为了排序用
        :param other:
        :return:
        """
        if self.weight < other.weight:
            return True
        else:
            return False

class Graph:
    """
    图结构
    """
    def __init__(self):
        self.nodes = dict()
        self.edges = set()

创建图

class GraphGenerator:
    """
    创建图
    """
    def createGraph(self, arr: List[List[int]]):
        graph = Graph()
        for i in range(len(arr)):
            weight = arr[i][0]
            src = arr[i][1]
            dst = arr[i][2]
            if src not in graph.nodes.keys():
                graph.nodes[src] = Node(src)

            if dst not in graph.nodes.keys():
                graph.nodes[dst] = Node(dst)

            src_node = graph.nodes.get(src)
            dst_node = graph.nodes.get(dst)
            edge = Edge(weight, src_node, dst_node)
            graph.edges.add(edge)

            src_node.out_degree += 1
            dst_node.in_degree += 1
            src_node.next_nodes.append(dst_node)
            src_node.edges.append(edge)

        return graph

图的遍历

广度优先搜索

class BFS:
    """
    图的宽度优先遍历
    """
    def bfs(self, start: Node):
        """
        从start这个node出发,进行宽度优先遍历
        :param start:
        :return:
        """
        if not start:
            return
        queue = list()
        node_set = set()
        queue.append(start)
        node_set.add(start)
        while queue:
            cur = queue.pop(0)
            print(cur.value)
            for node in cur.next_nodes:
                if node not in node_set:
                    node_set.add(node)
                    queue.append(node)

深度优先搜索

class DFS:
    """
    图的深度优先遍历
    """
    def dfs(self, start: Node):
        """
        从start这个node出发,进行深度优先遍历
        :param start:
        :return:
        """
        if not start:
            return
        stack = []
        node_set = set()
        stack.append(start)
        node_set.add(start)
        print(start.value)

        while stack:
            cur = stack.pop()
            for node in cur.next_nodes:
                if node not in node_set:
                    stack.append(cur)
                    stack.append(node)
                    node_set.add(node)
                    print(node.value)
                    break

图的拓扑排序

拓扑排序:即递归移除入度为0的节点。

class Record:
    def __init__(self, n: DirectedGraphNode, o: int):
        self.node = n
        self.deep = o

class TopologicalOrder:
    """
    图的拓扑排序
    即递归移除入度为0的节点
    """

    def dfs(self, graph: List[DirectedGraphNode]):
		"""
		深度优先拓扑
		"""
        def f(cur: DirectedGraphNode, order: Dict[DirectedGraphNode, Record]):
            if cur in order.keys():
                return order.get(cur)
            follow = 0
            for node in cur.neighbors:
                follow = max(follow, f(node, order).deep)
            ans = Record(cur, follow+1)
            order[cur] = ans

        order = dict()
        for cur in graph:
            f(cur, order)
        recordArr = list()
        for r in order.values():
            recordArr.append(r)
        recordArr.sort(key=lambda x: x.deep, reverse=False)
        ans = list()
        for r in recordArr:
            ans.append(r)
        return ans


    def bfs(self, graph: List[DirectedGraphNode]):
        """
        宽度优先拓扑
        等同于sort方法,只是图结构不同
        :param graph:
        :return:
        """
        in_degree_map = dict()
        for cur in graph:
            in_degree_map[cur] = 0

        for cur in graph:
            for nei_node in cur.neighbors:
                in_degree_map[nei_node] = in_degree_map.get(nei_node) + 1

        # 只有剩余入度为0的点,才进入这个队列
        zero_queue = list()
        for cur in in_degree_map.keys():
            if in_degree_map[cur] == 0:
                zero_queue.append(cur)

        ans = list()
        while zero_queue:
            cur = zero_queue.pop(0)
            ans.append(cur)
            for node in cur.neighbors:
                in_degree_map[node] = in_degree_map.get(node) - 1
                if in_degree_map[node] == 0:
                    zero_queue.append(node)

        return ans

    def sort(self, graph: Graph):
        # key 某个节点   value 剩余的入度
        in_degree_dc = dict()
        # 只有剩余入度为0的点,才进入这个队列
        zero_queue = list()
        for node in graph.nodes.values():
            in_degree_dc[node] = node.in_degree
            if node.in_degree == 0:
                zero_queue.append(node)

        res = list()
        while zero_queue:
            cur = zero_queue.pop(0)
            res.append(cur)

            for node in cur.next_nodes:
                in_degree_dc[node] = in_degree_dc.get(node) - 1
                if in_degree_dc.get(node) == 0:
                    zero_queue.append(node)

        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值