python数据结构实现(六):图及相关LeetCode题

本文详细介绍了如何使用Python实现图的邻接矩阵和邻接表表示,包括无向图、有向图及其有权图的构建。接着讨论了深度优先搜索和广度优先搜索,并应用Dijkstra算法求解最短路径。此外,还探讨了拓扑排序的Kahn算法和DFS算法,并通过LeetCode题目Number of Islands和Valid Sudoku来实践这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 图

1.1 python实现图的邻接矩阵表示方法

1.1.1 python实现无向无权图

  1. 通过传入一个二维数组确立邻接矩阵,无向无权图的邻接矩阵元素为0和1;
  2. adjMatrix[ i ][ j ] = 0 说明顶点i和j不连接,若为1则说明连接;
  3. 无向图的邻接矩阵总是为对称矩阵
import numpy as np  

class MatrixGraph:
    '''
    无向图的邻接矩阵表示(为对称矩阵)
    用矩阵存储顶点间的关系:顶点a与顶点b相连,则adjMatrix[vex2num[a],vex2num[b]]
    的值为1,否则为0
    vex2num为字典,将顶点映射为矩阵的编号
    '''
    def __init__(self,vertex=[]):
        '''
        根据传入的顶点信息表建造邻接矩阵和顶点字典
        :param vertex:无向图的所有顶点组成的列表
        '''
        self.vexNum = len(vertex)
        self.adjMatrix = np.zeros((self.vexNum,self.vexNum))
        self.vex2num = {}
        for index, vertex in enumerate(vertex):
            self.vex2num[vertex] = index
        
    def createGraph(self, maxtrix):
        '''
        传入一个矩阵确立顶点间的关系
        '''
        if maxtrix.shape == self.adjMatrix.shape:
            self.adjMatrix = maxtrix
        else:
            raise Exception('wrong matrix shape')
    
    def isLinked(self, vex1, vex2):
    	# 判断图中两个顶点是否连接
        return self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] == 1
    
    def linkVex(self, vex1, vex2):
        # 连接无向图的两个顶点
        if vex1 != vex2:
            self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] = 1
            self.adjMatrix[self.vex2num[vex2], self.vex2num[vex1]] = 1

    def splitVex(self, vex1, vex2):
        # 断开无向图的两个顶点
        self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] = 0
        self.adjMatrix[self.vex2num[vex2], self.vex2num[vex1]] = 0

生成无向无权图:

vexs = ['a','b','c','d','e']
Mgraph = MatrixGraph(vexs)
matrix = np.array([[0,1,1,0,0],[1,0,1,1,0],\
					[1,1,0,1,0],[0,1,1,0,1],[0,0,0,1,0]])
Mgraph.createGraph(matrix)      
print(Mgraph.adjMatrix)
Mgraph.isLinked('a','d')           
=====================================
[[0 1 1 0 0]
 [1 0 1 1 0]
 [1 1 0 1 0]
 [0 1 1 0 1]
 [0 0 0 1 0]]
 False

在这里插入图片描述

1.1.2 python实现无向有权图

  1. 无向有权图与无向无权图的区别仅在与邻接矩阵中的元素
  2. adjMatrix[i][j] 为路权大小则说明顶点i和j相连;若为inf则说明两个顶点间没有直接路径,即不相连
import numpy as np

inf = float('inf')
class MatrixGraph:
    '''
    无向有权图的邻接矩阵表示(为对称矩阵)
    用矩阵存储顶点间的关系:顶点a与顶点b相连,则adjMatrix[vex2num[a],vex2num[b]]的值为路权,否则为inf
    vex2num为字典,将顶点映射为矩阵的编号
    '''
    def __init__(self,vertex=[]):
        '''
        根据传入的顶点信息表建造邻接矩阵和顶点字典
        :param vertex:无向图的所有顶点组成的列表
        '''
        self.vex2num = {}
        self.vexNum = len(vertex)
        self.adjMatrix = np.array([[inf]*self.vexNum]*self.vexNum)
        
        for index, vertex in enumerate(vertex):
            self.vex2num[vertex] = index
        
    def createGraph(self, maxtrix):
        '''
        传入一个带权矩阵确立顶点间的关系
        '''
        if maxtrix.shape == self.adjMatrix.shape:
            self.adjMatrix = maxtrix
        else:
            raise Exception('wrong matrix shape')
    
    def isLinked(self, vex1, vex2):
        return not self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] == inf
    
    def linkVex(self, vex1, vex2, weight):
        # 连接无向图的两个顶点
        if vex1 != vex2:
            self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] = weight
            self.adjMatrix[self.vex2num[vex2], self.vex2num[vex1]] = weight

    def splitVex(self, vex1, vex2):
        # 断开无向图的两个顶点
        self.adjMatrix[self.vex2num[vex1], self.vex2num[vex2]] = inf
        self.adjMatrix[self.vex2num[vex2], self.vex2num[vex1]] = inf

生成无向有权图:

vexs = ['a','b','c','d','e']
Mgraph = MatrixGraph(vexs)
matrix = np.array([[inf,9,12,inf,9],[9,inf,7,10,inf],[12,7,inf,3,inf],\
					[inf,10,3,inf,14],[9,inf,inf,14,inf]])
Mgraph.createGraph(matrix)
print(Mgraph.adjMatrix)
print(Mgraph.isLinked('a','d'))
Mgraph.linkVex('a','d', 11)
print(Mgraph.adjMatrix)
print(Mgraph.isLinked('a','d'))
=================================
[[inf  9. 12. inf  9.]
 [ 9. inf  7. 10. inf]
 [12.  7. inf  3. inf]
 [inf 10.  3. inf 14.]
 [ 9. inf inf 14. inf]]
False
[[inf  9. 12. 11.  9.]
 [ 9. inf  7. 10. inf]
 [12.  7. inf  3. inf]
 [11. 10.  3. inf 14.]
 [ 9. inf inf 14. inf]]
True

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值