图结构的python实现

本文详细讲解了使用Python构建邻接矩阵和邻接链表图结构,并演示了DFS、BFS搜索算法以及判断无环图和进行拓扑排序的方法。
摘要由CSDN通过智能技术生成

以下为图结构的python实现:

from enum import Enum

GraphType = Enum('GraphType', ('undirected', 'directed', 'weighted'))

class MatrixGraph():
    """邻接矩阵类"""
    def __init__(self, vertex_list, edge_list, graph_type=GraphType.undirected):
        """
        用给定的顶点列表和边列表初始化一个邻接矩阵,可指定图类型。
        :param vertex_list: 顶点列表,包含图的所有顶点。
        :param edge_list: 边列表,在有向图和无向图中,每个元素是由两个顶点组成的元组;在加权图中,每个元素是由两个顶点和权重组成的元组。
        :param graph_type: 图类型,默认为无向图。
        """
        self.vertex_list = vertex_list
        self.adjacency_matrix = [[1 if i == j else 0 for j in self.vertex_list] for i in self.vertex_list]  # 初始化邻接矩阵,对角线值为1,其他为0
        self.graph_type = graph_type
        self.add_edge(edge_list)

    def add_edge(self, edge_list):
        """
        将边列表中的顶点关系添加进邻接矩阵中。
        :param edge_list: 边列表。
        :return: None
        """
        # 如果是有向图和无向图,邻接则将对应值置1
        if len(edge_list[0]) == 2:
            for v1, v2 in edge_list:
                i1 = self.vertex_list.index(v1)
                i2 = self.vertex_list.index(v2)
                self.adjacency_matrix[i1][i2] = 1
                if self.graph_type == GraphType.undirected: self.adjacency_matrix[i2][i1] = 1
        # 如果是加权图,邻接则将对应值置为权重
        elif len(edge_list[0]) == 3:
            for v1, v2, weight in edge_list:
                i1 = self.vertex_list.index(v1)
                i2 = self.vertex_list.index(v2)
                self.adjacency_matrix[i1][i2] = weight
                self.adjacency_matrix[i2][i1] = weight


class LinkedListGraph():
    """邻接链表类"""
    def __init__(self, vertex_list, edge_list, graph_type=GraphType.undirected):
        self.adjacency_dict = {vertex: [] for vertex in vertex_list}  # 初始化邻接字典
        self.graph_type = graph_type
        self.add_edge(edge_list)

    def add_edge(self, edge_list):
        """将顶点的邻居添加进对应列表中。"""
        for v1, v2 in edge_list:
            self.adjacency_dict[v1].append(v2)
            if self.graph_type == GraphType.undirected: self.adjacency_dict[v2].append(v1)

    def DFS(self, vertex, visited_list=[]):
        """
        深度优先搜索
        :param vertex: 当前顶点
        :param visited_list: 已访问顶点列表
        :return: None
        """
        print(vertex, end='\t')
        visited_list.append(vertex)
        for neighbor in self.adjacency_dict[vertex]:
            if neighbor not in visited_list:
                self.DFS(neighbor, visited_list)

    def BFS(self, vertex, visited_list=[]):
        """广度优先搜索"""
        if not visited_list:
            print(vertex, end='\t')
            visited_list.append(vertex)
        visit_list = []
        for neighbor in self.adjacency_dict[vertex]:
            if neighbor not in visited_list:
                print(neighbor, end='\t')
                visit_list.append(neighbor)
                visited_list.append(neighbor)
        for neighbor in visit_list:
            self.BFS(neighbor, visited_list)

    def is_acyclic_graph(self, vertex, visited_list=[]):
        """判断是否为无环图"""
        visited_list.append(vertex)
        for neighbor in self.adjacency_dict[vertex]:
            if neighbor in visited_list: return True
            if self.is_acyclic_graph(neighbor, visited_list): return True

    def top_sort(self):
        """拓扑排序"""
        def get_zero_degree(in_degree_dict):
            """获取入度为0的顶点"""
            return [key for key, value in in_degree_dict.items() if value == 0]

        # 计算入度
        in_degree_dict = {key: 0 for key in self.adjacency_dict}
        for neighbor_list in self.adjacency_dict.values():
            for neighbor in neighbor_list:
                in_degree_dict[neighbor] += 1
        # 如果是有向图且为无环图,则进行拓扑排序。
        if self.graph_type == GraphType.directed and self.is_acyclic_graph(get_zero_degree(in_degree_dict)[0]):
            # 每次输出入度为0的顶点,并将其指向的所有顶点入度减1。
            while get_zero_degree(in_degree_dict):
                for vertex in get_zero_degree(in_degree_dict):
                    print(vertex, end='\t')
                    for neighbor in self.adjacency_dict[vertex]:
                        in_degree_dict[neighbor] -= 1
                    del in_degree_dict[vertex]
        else: print('不是DAG,不可拓扑排序!')


if __name__ == '__main__':
    vertex_list = ['a', 'b', 'c', 'd', 'e', 'f']
    edge_list = [('a', 'b'), ('a', 'c'), ('b', 'd'), ('c', 'e'), ('c', 'f')]
    obj = MatrixGraph(vertex_list, edge_list)
    print('邻接矩阵:', obj.adjacency_matrix)
    obj = LinkedListGraph(vertex_list, edge_list)
    print('邻接链表:', obj.adjacency_dict)
    print('DFS遍历:'); obj.DFS('a')
    print('\n', 'BFS遍历:'); obj.BFS('a')
    vertex_list = [chr(i) for i in range(65, 78)]
    edge_list = [('A', 'B'), ('A', 'F'), ('A', 'G'), ('C', 'A'), ('C', 'D'), ('D', 'F'), ('F', 'E'), ('G', 'E'),
                 ('G', 'J'), ('H', 'G'), ('I', 'H'), ('J', 'K'), ('J', 'L'), ('J', 'M'), ('L', 'M')]
    obj = LinkedListGraph(vertex_list, edge_list, GraphType.directed)
    print('\n', 'DAG:', obj.adjacency_dict)
    print('拓扑排序:'); obj.top_sort()

输出:

邻接矩阵: [[1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 0, 1, 1], [0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 0, 1]]
邻接链表: {'a': ['b', 'c'], 'b': ['a', 'd'], 'c': ['a', 'e', 'f'], 'd': ['b'], 'e': ['c'], 'f': ['c']}
DFS遍历:
a	b	d	c	e	f	
 BFS遍历:
a	b	c	d	e	f	
 DAG: {'A': ['B', 'F', 'G'], 'B': [], 'C': ['A', 'D'], 'D': ['F'], 'E': [], 'F': ['E'], 'G': ['E', 'J'], 'H': ['G'], 'I': ['H'], 'J': ['K', 'L', 'M'], 'K': [], 'L': ['M'], 'M': []}
拓扑排序:
C	I	A	D	H	B	F	G	E	J	K	L	M	

  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值