图的存储表示

news2024/12/23 23:56:41

目录

      概述

       图的定义

       图的存储结构

       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))

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你好!Python

目录 写在前面 编辑推荐 内容简介 作者简介 前言 推荐理由 写在后面 写在前面 本期博主给大家推荐一本全新出版的Python图书,感兴趣的小伙伴一起来看看吧! 《你好!Python 全彩印刷 从零开始学 语言轻松幽默 版式精美 视频讲解 提供代…

成功的管理者必做的10件事

管理者是团队的核心,他们不仅要有出色的领导能力,还要具备应对各种挑战的智慧和勇气。以下是成功的管理者必做的10件事: 1、设定明确的目标 管理者要为团队设定清晰、可衡量且具有挑战性的目标,这些目标不仅与组织的长期愿景相…

高考志愿填报,如何分析自己的优势特长?

据不完全统计,80%的高三学生,不清楚自己要报什么专业,以及将来从事哪种职业?有的人则是完全听从父母的安排,有人听老师的建议,有人追热门,有人查什么专业可以拿高薪.... 而现实就是&#xff1a…

水产养殖监测站的工作原理

TH-LSZ06水产养殖监测站是保障水产质量安全的重要设施,监测水产养殖环境:负责监测水产养殖基地的水质、底泥、养殖物质等,确保养殖环境的适宜性和安全性。通过对养殖环境的实时监测,可以及时发现和预警水产疾病和污染问题&#xf…

pdf文件怎么改变大小?在线快速压缩pdf的方法

pdf作为一种常用的文件格式,使用这种文件类型的好处在于不仅拥有更好的兼容性,还可以设置密码来保证安全性,防止未授权用户查看内容,所以现在导出文件展示都会采用这种格式的来做内容展示。当遇到pdf文件过大问题时,想…

Unity | Tilemap系统

目录 一、准备工作 1.插件导入 2.资源导入 二、相关组件介绍 1.Grid组件 2.Tilemap组件 3.Tile 4.Tile Palette 5.Brushes 三、动态创建地图 四、其他功能 1.移动网格上物体 2.拖拽缩放地图 Unity Tilemap系统为2D游戏开发提供了一个直观且功能强大的平台&#xff…

知网学术期刊《数学之友》投稿难度大吗?

知网学术期刊《数学之友》投稿难度的大小,实际上取决于多个因素的综合考量,包括论文的质量、研究方向的匹配度、期刊的审稿标准以及投稿者的学术背景等。 首先,从期刊的定位和特点来看,《数学之友》作为一份专注于数学领域的学术期…

利用R包“Phenotype”对表型值进行检查

首先,你需要确保你已经安装了R和RStudio(如果你想用RStudio的话)。然后,你可以按照以下步骤进行操作: 加载数据:首先,你需要加载你的表型数据。如果你的数据是以CSV、Excel等格式保存的&#x…

vue2中如何动态渲染组件

vue2中如何动态渲染组件 动态渲染组件代码解读通过函数调用渲染组件 封装一个函数调用的二次确认弹窗如何让外部知道用户点击了取消还是确定呢? 思考小结 vue2 的项目中,main.js 文件中有一个挂载 App.vue 组件的方法: new Vue({name: Root,…

Python酷库之旅-比翼双飞情侣库(01)

目录 一、xlrd库的由来 二、xlrd库优缺点 1、优点 1-1、支持多种Excel文件格式 1-2、高效性 1-3、开源性 1-4、简单易用 1-5、良好的兼容性 2、缺点 2-1、对.xlsx格式支持有限 2-2、功能相对单一 2-3、更新和维护频率低 2-4、依赖外部资源 三、xlrd库的版本说明 …

Linux C语言:多级指针(void指针和const)

一、多级指针 把一个指向指针变量的指针变量&#xff0c;称为多级指针变量对于指向处理数据的指针变量称为一级指针变量指向一级指针变量的指针变量称为二级指针变量 1、二级指针变量的说明形式 <数据类型> ** <指针名> &#xff1b; 一张图理解二级指针 2、多…

intouch的报警怎么发到短信/微信上

Intouch 与 GRM_OPCGATE 通讯协议 一、安装 FS GateWay&#xff08;INTOUCH 驱动盘里有这个驱动程序&#xff0c;根目录:\INTOUCH10.0\DA Server\WW\FSG-1.5.100&#xff09; 。注&#xff1a;安装 INTOUCH 时&#xff0c;可能已同时安装了这个驱动&#xff0c;如图在下查看&am…

【Java】如何提升RocketMQ顺序消费性能?

一、问题解析 我们先来了解一下 RocketMQ 顺序消费的实现原理。RocketMQ 支持局部顺序消息消费&#xff0c;可以保证同一个消费队列上的消息顺序消费。例如&#xff0c;消息发送者向主题为 ORDER_TOPIC 的 4 个队列共发送 12 条消息&#xff0c; RocketMQ 可以保证 1、4、8 这…

ultralytics框架讲解

ultralytics简介 Ultralytics是一个开源的计算机视觉和深度学习框架&#xff0c;旨在简化训练、评估和部署视觉模型的过程。该框架提供了一系列流行的视觉模型&#xff0c;包括YOLOv5、YOLOv4、YOLOv3、YOLOv3-tiny、YOLOv5-tiny、EfficientDet、PAN、PP-YOLO等&#xff0c;并提…

西门子PLC数据 转IEC61850项目案例

1 案例说明 设置网关采集西门子PLC数据把采集的数据转成IEC61850协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协议转换网关&#xff0c;是把一种协议转换成另外一种协议。网关可以采集西门子&#xff0c;欧姆龙&#xff0c;三菱&#xff0c;AB PLC&#xff0c;DLT6…

【Ardiuno】实验ESP32单片机完成搭建简易Web服务器功能(图文)

今天&#xff0c;小飞鱼继续来测试使用ESP32来实现简易的wifi无线web服务器功能。使用Ardiuno平台编辑器输入以下示例代码&#xff1a; #include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> #include <ESPmDNS.h>const char* ssid &q…

QT安装及项目创建

一、QT安装 1、安装qt_creater 方法一&#xff1a; 镜像文件&#xff1a;在2024-6-12&#xff1a;版本已经更新到了6.7 下载地址&#xff1a;https://download.qt.io/archive/qt/ 方法二&#xff1a; 百度网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1D0EmH…

ssm大学校园慈善拍卖网站-计算机毕业设计源码80891

摘要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对大学校园慈善拍卖网站等问题&#xff0c;对大…

软考-架构设计师-综合知识总结(试卷:2009~2022)(下篇)

说明 本文档对2009到2022年试卷的综合知识进行了归纳总结&#xff0c;同时对叶宏主编的《系统架构设计师教程》划分重点。 第十七章&#xff1a;通信系统架构设计 17.2 考题总结 第十八章&#xff1a;安全架构设计 18.1 重要知识点 18.2 考题总结 第十九章&#xff1a;大数据…

半导体晶圆切割之高转速电主轴解决方案

随着科技的飞速进步&#xff0c;集成电路技术已经成为了现代电子设备中不可或缺的核心组件。而在集成电路的生产过程中&#xff0c;半导体晶圆切割技术更是扮演着举足轻重的角色。这不仅关系到半导体芯片的制造成本和效率&#xff0c;更是决定了整个集成电路产业的发展速度和方…