Python数据结构之图的存储结构详解

yizhihongxing

Python数据结构之图的存储结构详解

什么是图

图是一种数据结构,用于表示不同对象之间的关系。在图中,对象通常表示为称为顶点的节点,而它们之间的关系称为边。边可以是无向的(没有方向)或有向的(有方向)。图分为有向图和无向图两种类型,根据边是否有方向来区别。

无向图

在无向图中,边没有方向,例如下图:

A -- B
|    |
C -- D

上面的图表示四个顶点 A,B,C 和 D 之间的关系,它们之间的边是无向的。例如,从顶点 A 到顶点 D 有两条路径: A -> B -> D 和 A -> C -> D。

有向图

在有向图中,边是有方向的,例如下图:

A -> B
|    |
v    v
C <- D

上图表示四个顶点 A,B,C 和 D 之间关系的有向图。它们之间的边是有方向的。例如,顶点 A 到顶点 D 之间的路径是 A -> C -> D。

图的存储结构

图的存储结构包含两种方式:邻接矩阵和邻接表。

邻接矩阵

邻接矩阵使用二维数组来表示图的顶点之间的关系。如果一个图有 N 个顶点,那么它的邻接矩阵就是 N x N 的方阵。数组中的每个元素表示一条边,如果两个顶点之间存在边,则它们之间的值为 1,否则为 0。

例如,下面的图可以用邻接矩阵来表示:

     A    B    C
A    0    1    1
B    1    0    1
C    1    1    0

上图中,每一行和每一列代表一个顶点,如果两个顶点之间有连线,则矩阵中对应位置的值为 1,否则为 0。

邻接表

邻接表使用链式数据结构来表示图的顶点之间的关系。邻接表的每个顶点都使用一个链表来存储与它相关的顶点。对于一个无向图,图中的每个顶点都与与它相邻的顶点相连。对于一个有向图,每个顶点有两个链表,一个链表存储指向该顶点的所有顶点,另一个链表存储该顶点可以到达的所有顶点。

例如,下面的图可以用邻接表来表示:

A -> B -> C
B -> A -> C
C -> A -> B

上图中,每一行代表一个顶点和与它相关的所有顶点的链表。在这个例子中,每个链表都只有一个节点,因为每个顶点只与另外两个顶点相连。

示例说明

使用邻接矩阵表示图

以下 Python 代码示例演示了如何使用邻接矩阵来表示一个无向图:

class Graph:
    def __init__(self, num_vertices):
        self.num_vertices = num_vertices
        self.adjacency_matrix = [[0] * num_vertices for _ in range(num_vertices)]

    def add_edge(self, i, j):
        self.adjacency_matrix[i][j] = 1
        self.adjacency_matrix[j][i] = 1

    def __repr__(self):
        return '\n'.join([' '.join([str(self.adjacency_matrix[i][j]) for j in range(self.num_vertices)]) for i in range(self.num_vertices)])

g = Graph(4)
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 3)

print(g)

输出结果如下:

0 1 1 0
1 0 1 0
1 1 0 1
0 0 1 0

使用邻接表表示图

以下 Python 代码示例演示了如何使用邻接表来表示一个无向图:

class Node:
    def __init__(self, val):
        self.val = val
        self.neighbors = []

class Graph:
    def __init__(self):
        self.adjacency_list = {}

    def add_edge(self, node1, node2):
        if node1 not in self.adjacency_list:
            self.adjacency_list[node1] = Node(node1)
        if node2 not in self.adjacency_list:
            self.adjacency_list[node2] = Node(node2)
        self.adjacency_list[node1].neighbors.append(self.adjacency_list[node2])
        self.adjacency_list[node2].neighbors.append(self.adjacency_list[node1])

    def __repr__(self):
        res = ""
        for node in self.adjacency_list:
            res += str(node) + " -> "
            for neighbor in self.adjacency_list[node].neighbors:
                res += str(neighbor.val) + " "
            res += "\n"
        return res

g = Graph()
g.add_edge("A", "B")
g.add_edge("A", "C")
g.add_edge("B", "C")
g.add_edge("C", "D")

print(g)

输出结果如下:

A -> B C 
B -> A C 
C -> A B D 
D -> C 

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python数据结构之图的存储结构详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • vuex学习总结

    Vuex学习总结 简介 Vuex是Vue.js的状态管理库,用于管理应用程序中的状态。通过Vuex,我们可以将应用程序中的状态集中管理,提高代码的可维护性和可扩展性。 核心概念 Vuex中有以下几个核心概念: State:状态,即应用程序中的数据。 Getter:获取器,用于从状态中获取数据。 Mutation:变更,用于修改状态。 Action:动作,用于…

    other 2023年5月7日
    00
  • Go语言基础go install命令使用示例详解

    Go语言基础:go install命令使用示例详解 介绍 在Go语言中,go install命令用于编译并安装指定的包或可执行文件。它是Go语言构建工具链中的一个重要命令,可以方便地将代码编译成可执行文件,并将其安装到指定的目录中。 使用示例 示例一:安装可执行文件 假设我们有一个名为hello.go的源代码文件,内容如下: package main imp…

    other 2023年9月7日
    00
  • linux终端使用ss代理

    Linux终端使用ss代理 在Linux终端中使用ss代理是一种非常常见的操作,这也是由于许多时候,我们需要在终端中进行一些网络请求,例如使用curl、wget等命令下载文件,所以需要使用代理来达到我们的目的。 以下是在Linux终端中使用ss代理的步骤。 安装ss客户端 首先,我们需要安装ss客户端。在Ubuntu等Debian系列Linux发行版中,可以…

    其他 2023年3月29日
    00
  • C语言驱动开发之判断自身是否加载成功详解

    C语言驱动开发之判断自身是否加载成功详解 在C语言驱动开发中,驱动程序的加载与卸载是一个非常重要的环节,而判断驱动程序是否加载成功也是非常重要的一步。 一、判断驱动是否加载成功的方法 通过检查设备管理器中的设备状态来判断驱动是否加载成功。 通过检查日志文件来判断驱动是否加载成功。 通过编写测试工具来测试驱动程序是否加载成功。一般测试工具包含以下几个部分: 测…

    other 2023年6月25日
    00
  • Android开发使用Message对象分发必备知识点详解

    一、什么是Message对象 Message是android.os包下的一个类,它代表了一个消息对象,用于在不同的线程之间传递信息,通常用于Handler与Looper之间的通信。在Android开发中,使用Message对象来分发消息非常常见,因此,掌握Message对象的用法和原理至关重要。 二、Message对象的创建和使用 创建Message对象的方…

    other 2023年6月27日
    00
  • Android Studio 下 Flutter 开发环境搭建过程

    下面我为你详细讲解“Android Studio 下 Flutter 开发环境搭建过程”的完整攻略: 1. 确认前置条件 在安装 Flutter 并使用 Android Studio 进行开发之前,你需要确认几个前置条件是否都已经满足了,这些前置条件包括: 确认你的电脑系统是否符合 Flutter 的要求,Flutter 可以运行在以下系统上:Windows…

    other 2023年6月27日
    00
  • 如何使用Python一键修改上万个文件名

    如何使用Python一键修改上万个文件名 修改文件名是计算机日常操作之一,但是当文件数量较多时手动修改是不可取的。Python作为一种简单易用的编程语言,可以帮助我们轻松一键修改上万个文件名。 以下是完整的攻略: 确定目标文件夹 首先需要确定需要修改文件名的目标文件夹,建议将所有需要修改的文件都放在同一文件夹中。可以使用Python的os模块读取目标文件夹中…

    other 2023年6月26日
    00
  • 浅谈vue首屏加载优化

    浅谈Vue首屏加载优化 Vue的首屏加载速度是用户体验的重要因素之一,能够有效地提高网站的转化率和用户的满意度。下面介绍一些Vue首屏加载优化的方法。 1. 减少组件数量 首先,我们需要尽可能地减少首屏需要加载的组件数量。不必要的组件我们可以合并或者延迟加载。比如,在页面初始渲染时,我们可以只加载用户在当前状态下所需的组件,其余组件采用懒加载的方式,等到需要…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部