图的存储表示

目录

      概述

       图的定义

       图的存储结构

       1)邻接矩阵

       2)邻接表

        3)十字链表

        4)邻接多重表


      概述

      数据结构分为两类,一类是具有递归结构的数据结构,也就是可以给出一个递归定义的数据结构,一类是非递归结构的数据结构。像链表、数组、广义表、树、FA等都是具有递归结构的数据结构,都可以给出一个递归的定义,比如说树,它的递归定义如下:

       basis:空树是一棵树,一个结点的树是一棵树

       induction:各个以树的根结点的子结点为根结点的结构是树

       关于树的讨论已经进行了很多,这里不再赘述,这篇文章讲一下非递归结构的数据结构:图。

       图的定义

       图不是一个递归结构的数据结构,也就没法给出一个递归定义,图的定义可以用一个三元组来表示:顶点集、弧/边集、操作集,在图的图形表示里,顶点用一个小圆圈表示,弧用一条有向边来表示,若图中存在一条顶点v到顶点w的弧,由v引一条指向w的弧来表示,v为弧的弧尾,w为弧的弧头。图分为有向图和无向图,无向图是有向图的一种特例,它是一种具有对称性质的有向图,也就是如果从顶点v到顶点w存在一条弧,那么从顶点w到顶点v也必存在一条弧,也就是顶v和顶点w之间存在两条有向边,为了简化表示,用一条连接顶点v、w的无向边表示。图的常见操作有求顶点的所有弧/边,求顶点的度,求图的联通子图,求联通图的最小生成树,对联通图进行遍历,求两个顶点之间的最短路径等。

       图的存储结构

       

       1)邻接矩阵

       顶点集用一个list表示

       弧集用一个临接矩阵表示

       matrix[i][j]取0表示顶点i到顶点j不存在一条弧,取1表示顶点i到顶点j存在一条弧

       如果是无向图,可以采用上三角/下三角矩阵进行压缩存储,可以节省一半空间

class Vertex:
    def __init__(self, data = None):
        self.data = data

class Graph:
    def __init__(self, vertexs):
        self.vertexs = [i for i in vertexs]
        self.matrix = [[0] * len(vertexs) for i in range(len(vertexs))]

    def set_arc(self, i, j):
        self.matrix[i][j] = 1

    def unset_arc(self, i, j):
        self.matrix[i][j] = 0

    def get_in_arcs(self, i):
        return [(j, i) for j, k in enumerate(self.matrix) if k[i]]
        
    def get_out_arcs(self, i):
        return [(i, j) for j, k in enumerate(self.matrix[i]) if k]
    
    def __str__(self):
        graphmatrix = ""
        for i in self.matrix:
            graphmatrix += " ".join([str(j) for j in i]) + '\n'
        return graphmatrix

g1 = Graph([Vertex() for i in range(4)])
g1.set_arc(0, 1)
g1.set_arc(0, 2)
g1.set_arc(2, 3)
g1.set_arc(3, 0)
print(g1)
print(g1.get_in_arcs(0))
print(g1.get_in_arcs(1))
print(g1.get_in_arcs(2))
print(g1.get_in_arcs(3))
print(g1.get_out_arcs(0))
print(g1.get_out_arcs(1))
print(g1.get_out_arcs(2))
print(g1.get_out_arcs(3))

       2)邻接表

       顶点集存储在一个list中

       每个顶点维护一个list,存储它所有的出弧

       为了方便求顶点的所有入弧,顶点可以再维护一个list,以存储它所有的入弧

       邻接表表示法实际用一个邻接点表示一条弧

       临接表的存储密度比临接矩阵大,更节省空间,但要判断任意两个顶点之间是否有弧/边不如临接矩阵效率高

class Vertex:
    def __init__(self, data = None):
        self.data = data
        self.in_arcs = []
        self.out_arcs = []

    def set_in_arc(self, v):
        self.in_arcs.append(v)

    def set_out_arc(self, v):
        self.out_arcs.append(v)

class Graph:
    def __init__(self, vertexs = None):
        self.vertexs = [i for i in vertexs] if vertexs else []
    
    def insert_vertex(self, vertex):
        self.vertexs.append(vertex)

    def set_in_arc(self, i, j):
        vertex = self.vertexs[i]
        vertex.set_in_arc(j)

    def set_out_arc(self, i, j):
        vertex = self.vertexs[i]
        vertex.set_out_arc(j)

    def set_in_arcs(self):
        for i, v in enumerate(self.vertexs):
            for j in v.out_arcs:
                self.vertexs[j].set_in_arc(i)

    def get_in_arcs(self, i):
        return [(j, i) for j in self.vertexs[i].in_arcs]

    def get_out_arcs(self, i):
        return [(i, j) for j in self.vertexs[i].out_arcs]

g = Graph(Vertex() for i in range(4))
g.set_out_arc(0, 1)
g.set_out_arc(0, 2)
g.set_out_arc(2, 3)
g.set_out_arc(3, 0)
g.set_in_arcs()
print(g.get_in_arcs(0))
print(g.get_in_arcs(1))
print(g.get_in_arcs(2))
print(g.get_in_arcs(3))
print(g.get_out_arcs(0))
print(g.get_out_arcs(1))
print(g.get_out_arcs(2))
print(g.get_out_arcs(3))

        3)十字链表

        临接表中给一条弧创建了两个弧结点,因为一条弧,它既作为弧尾顶点的出弧,又作为弧头顶点的入弧,为了避免这种重复,可以给弧结点以更多的信息,指明弧的弧头和弧尾,并把它同时加入弧头的入弧list和弧尾的出弧list中。

class Vertex:
    def __init__(self, data = None):
        self.data = data
        self.in_arcs = []
        self.out_arcs = []

    def set_in_arc(self, arc):
        self.in_arcs.append(arc)

    def set_out_arc(self, arc):
        self.out_arcs.append(arc)

class Arc:
    def __init__(self, tail, head, data = None):
        self.tail = tail
        self.head = head
        self.data = data

class Graph:
    def __init__(self, vertexs = None):
        self.vertexs = [i for i in vertexs] if vertexs else []
    
    def insert_vertex(self, vertex):
        self.vertexs.append(vertex)

    def set_arc(self, arc):
        self.vertexs[arc.tail].set_out_arc(arc)
        self.vertexs[arc.head].set_in_arc(arc)

    def get_in_arcs(self, i):
        return [(j.tail, i) for j in self.vertexs[i].in_arcs]

    def get_out_arcs(self, i):
        return [(i, j.head) for j in self.vertexs[i].out_arcs]

g = Graph(Vertex() for i in range(4))
g.set_arc(Arc(0, 1))
g.set_arc(Arc(0, 2))
g.set_arc(Arc(2, 3))
g.set_arc(Arc(3, 0))

print(g.get_in_arcs(0))
print(g.get_in_arcs(1))
print(g.get_in_arcs(2))
print(g.get_in_arcs(3))
print(g.get_out_arcs(0))
print(g.get_out_arcs(1))
print(g.get_out_arcs(2))
print(g.get_out_arcs(3))

        4)邻接多重表

       上面的各种存储表示都是关于有向图的,当然对他们稍加改造/约束就可以得到一个无向图的表示。邻接多重表是对十字链表表示做了一点修改得来的,用于表示无向图。无向图的边,它没有头、尾的概念,只需指明它连接的两个顶点,并把它加入到两个顶点的边集中即可。

class Vertex:
    def __init__(self, data = None):
        self.data = data
        self.edges = []

    def set_edge(self, edge):
        self.edges.append(edge)

class Edge:
    def __init__(self, one, other, data = None):
        self.one = one
        self.other = other
        self.data = data

class Graph:
    def __init__(self, vertexs = None):
        self.vertexs = [i for i in vertexs] if vertexs else []
    
    def insert_vertex(self, vertex):
        self.vertexs.append(vertex)

    def set_edge(self, edge):
        self.vertexs[edge.one].set_edge(edge)
        if edge.one != edge.other:
            self.vertexs[edge.other].set_edge(edge)

    def get_edges(self, i):
        edges = []
        for j in self.vertexs[i].edges:
            if j.one == i:
                edges.append((i, j.other))
            else:
                edges.append((i, j.one))
        return edges

g = Graph(Vertex() for i in range(4))
g.set_edge(Edge(0, 1))
g.set_edge(Edge(0, 2))
g.set_edge(Edge(2, 3))
g.set_edge(Edge(3, 0))
print(g.get_edges(0))
print(g.get_edges(1))
print(g.get_edges(2))
print(g.get_edges(3))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/703044.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Offline : How to Leverage Diverse Demonstrations in Offline Imitation Learning

ICML 2024 paper code Intro 文章提出一种从混合质量数据中高效抽取有用状态动作数据用于模仿学习。算法基于一种假设,即使当前状态并非属于专家状态,但是若在该状态下采取动作导致下一状态是专家状态,那么该状态相较于随机状态更有价值。 …

AI赋能银行国际结算审单:合合信息抽取技术的实践与应用

官.网地址:合合TextIn - 合合信息旗下OCR云服务产品 时下,银行国际业务是金融体系的重要组成部分,涵盖了外汇交易、国际结算、贸易融资、跨境投资等领域,这些业务对于国际贸易和全球经济发展具有重要作用。国际业务部门单据、凭证…

ffmpeg实现视频播放 ----------- Javacv

什么是Javacv和FFmpeg? Javacv是一个专门为Java开发人员提供的计算机视觉库,它基于FFmpeg和Opencv库,提供了许多用于处理图 像、视频和音频的功能。FFmpeg是一个开源的音视频处理工具集,它提供了用于编码、解码、转换和播放音视频…

LabVIEW RT环境中因字符串拼接导致的系统崩溃问题

在LabVIEW实时操作系统(RT)环境中运行的应用程序出现字符串拼接后死机的问题,通常涉及内存管理、内存泄漏或其他资源管理问题。以下是一些指导和步骤,帮助解决这个问题: 1. 内存泄漏检测 字符串拼接会在内存中创建新…

Android Glide loading Bitmap from RESOURCE_DISK_CACHE slow,cost time≈2 seconds+

Android Glide loading Bitmap from RESOURCE_DISK_CACHE slow,cost time≈2 seconds 加载一张宽高约100px多些的小图,是一张相当小的正常图片,loading Bitmap from RESOURCE_DISK_CACHE竟然耗时达到惊人的3秒左右!(打开Glide调试…

XSKY 在金融行业:新一代分布式核心信创存储解决方案

近日,国家金融监督管理总局印发了《关于银行业保险业做好金融“五篇大文章”的指导意见》,在数字金融领域提出明确目标,要求银行业保险业数字化转型成效明显,数字化经营管理体系基本建成,数字化服务广泛普及&#xff0…

python实战根据excel的文件名称这一列的内容,找到电脑D盘的下所对应的文件位置,要求用程序实现

今天客户需要 根据excel的文件名称这一列的内容,找到电脑D盘的下所对应的文件位置,要求用程序实现 数据样例:记录.xlsx 解决代码: 1、安装必要的库: pip install pandas openpyxl2、编写Python脚本: im…

国际贸易条件简称的解析说明

声明:本文仅代表作者观点和立场,不代表任何公司!仅用于SAP软件应用学习参考。 SAP创建销售订单的界面有个国际贸易条件的字段,这个字段选择值主要有如下选择值,国际贸易条件简称的具体解析说明如下: EXW &…

CAD2022下载与安装

CAD2022下载与安装 安装包下载安装包解压缩软件安装安装完成 安装包下载 安装包下载链接: https://pan.xunlei.com/s/VNyyAVUev-7XHig_2VIGiTN1 提取码:mxt8 下载安装包,完成后,得到一个压缩文件 安装包解压缩 右键解压到当前…

D-Bus——system 调用session 报错

以下代码是一个 session 服务和 systemd 服务 demo &#xff1a; systemd DBus #include <QCoreApplication> #include <QDBusConnection> #include <QDBusInterface> #include <QDBusError> #include <QDebug>class TestObject : public QObje…

如何清理鼠标右键的一些无用的选项

清理鼠标右键出现的无用&#xff08;无效&#xff09;选项 最近安装了很多乱七八糟的软件&#xff0c;之后也手动卸载了不少&#xff0c;但使用鼠标右键点击文件夹的时候&#xff0c;发现多了一些我不知道&#xff0c;或者说是我不想用的情况&#xff0c;目前情况已经解决&…

nginx rewrite地址重写

常用的nginx正则表达式 ^匹配以...开头的字符串$匹配以...结尾的字符串^$^$表示空行*匹配前面的字符0次或者多次&#xff08;通配符*表示任意数量的任意字符&#xff09;匹配前面的字符1次或多次?匹配前面的字符0次或1次.匹配除了“\n”之外的任意单个字符&#xff0c;[.\n]表…

两种AI 图像生成技术:MidJourney 和 Stable Diffusion

目录 1、MidJourney1.1 MidJourney基本特点1.2 MidJourney的玩法教程 2、Stable Diffusion2.1 Stable Diffusion基本特点&#xff1a;2.2 Stable Diffusion生成展示 3、两种技术的区别4、AI 绘画与它们的联系5、总结 MidJourney 和 Stable Diffusion 是当前两种流行的 AI 图像生…

最短路:spfa算法

最短路&#xff1a;spfa算法 题目描述参考代码![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/3be484da34a84911a0a7dab3f1d84945.png) 题目描述 参考代码 输入示例 3 3 1 2 5 2 3 -3 1 3 4输出示例 2#include <iostream> #include <cstring> #inc…

每天五分钟计算机视觉:如何在现有经典的卷积神经网络上进行微调

本文重点 在深度学习领域,卷积神经网络(Convolutional Neural Networks,CNN)因其强大的特征提取和分类能力而广泛应用于图像识别、自然语言处理等多个领域。然而,从头开始训练一个CNN模型往往需要大量的数据和计算资源,且训练时间较长。幸运的是,迁移学习(Transfer Le…

【电子通识】焊接常见的不良有哪些?

在焊接完成后的调试阶段&#xff0c;有时总会发生一些奇怪的异常。也许是因为在焊接过程中出现了一些莫名其妙的焊接缺陷&#xff0c; 这些焊接缺陷产生的原因各不相同。 在实际的SMT贴片加工或插件焊接中&#xff0c;我们一般会采取一些方法来避免这些焊接不良的现象。那么常见…

247 H指数

法一&#xff1a; 不进行排序&#xff0c;直接依照原数组进行解&#xff0c;先假设h为1&#xff0c;然后找引用超过1篇的论文数量&#xff0c;如果满足&#xff0c;则再假设h为2。这样比较慢&#xff0c;时间复杂度为o(n方)。 int hIndex(vector<int>& citations) {…

我的编程语言学习记录:一段不断探索的旅程

目录 我的编程语言学习记录&#xff1a;一段不断探索的旅程 1.引言 2.我的编程之旅开始 第一站&#xff1a;Python — 简洁之美 第二站&#xff1a;JavaScript — 网页的魔法 第三站&#xff1a;Java — 企业级的力量 3.学习过程中的挑战与克服 1.理解概念 3.记忆语法…

Linux命令详解(1)

在Linux操作系统中&#xff0c;命令行界面&#xff08;CLI&#xff09;是一个强大的工具&#xff0c;它允许用户通过键入命令来与系统交互。无论是系统管理员还是普通用户&#xff0c;掌握一些基本的Linux命令都是非常重要的。在本文中&#xff0c;我们将探讨一些常用的Linux命…

文字悬停效果

文字悬停效果 效果展示 CSS 知识点 CSS 变量使用回顾-webkit-text-stroke 属性的运用与回顾 页面整体结构实现 <ul><li style"--clr: #e6444f"><a href"#" class"text">First</a></li><li style"--cl…