图及图的存储

news2024/11/15 21:43:01

目录

1.图的相关概念

2.图的存储

2.1.直接存法

 1.查询是否存在某条边

2.遍历一个点的所有出边

3..遍历整个图

应用

2.2.邻接矩阵

 1.查询是否存在某条边

2.遍历一个点的所有出边

3..遍历整个图

应用

2.3.邻接表

 1.查询是否存在某条边

2.遍历一个点的所有出边

3..遍历整个图

应用

2.4.链式前向星

应用


1.图的相关概念

在图论中,有一些核心概念和基本术语,这些概念对于理解和处理图结构非常重要。以下是一些常见的图论概念梳理:

有向图:

无向图:

1.图 (Graph):图是由点集合及连接这些点的边集合组成的数学结构。图的点通常称为“顶点”(vertices),而连接顶点的线或弧称为“边”(edges)。

2.简单图 (Simple graph)与完全图:简单图是没有重复边和重复顶点的图。也就是说,在简单图中,任何两个不同的顶点之间最多只有一条边,并且不存在顶点到边,除了自环。完全图是一种简单图,其中任意两个不同的顶点之间都有一条边。

3.自环 (Loop):自环是指顶点自身相连的边。即一个顶点与自身的一条边。

4.重边:重边是指在图中连接相同两个顶点的边,如果有两条或多条边连接同一个顶点对,则这些边称为重边。

5.点边关联:点边关联是指图中的每个顶点都与零条或多条边相关联。

6.边相邻,点相邻:边相邻:如果两条边共享一个顶点,则这两条边是边相邻的。点相邻:如果两个顶点之间存在一条边,则这两个顶点是点相邻的。

7.度 (Degree):顶点的度是指与该顶点相邻的边的数量。即连接到该顶点的边的条数。

8.孤立点 (Isolated vertex):孤立点是指度为零的顶点,即没有与其他顶点相连的顶点。

9.叶节点 (Leaf vertex):叶节点,也称为终端节点,是指度为1的顶点,即只与一个顶点相连的顶点。

10.偶点 (Even vertex):偶点是指度的度数为偶数的顶点。

11.奇点 (Odd vertex):奇点是指度的度数为奇数的顶点。

12.最小度 (Minimum degree):最小度是指图中所有顶点中最小的度值。

13.最大度 (Maximum degree):最大度是指图中所有顶点中最大的度值。

14.出度 (Outdegree)与入度 (Indegree):出度是指从某个顶点出发的边的数量,入度是指指向某个顶点的边的数量。

15. k−正则图k−Regular Graph):k−正则图是指所有顶点的度都是k的图。

16.同构 (Isomorphism):如果两个图在结构上完全相同,即它们具有相同的顶点和边,并且这些边连接相同的顶点对,那么这两个图是同构的。

17.途径 (Walk):图中的一条路径是一系列顶点的序列,其中每一对相邻顶点之间都有一条边或弧。路径可以有方向或无方向。

18.迹 (Trail):迹是图中的一条路径,除了允许重复经过相同的边,不允许经过相同的顶点。

19.路径 (Path):路径是图中的一条无重复边的序列,每个顶点只一次,除了第一个和最后一个顶点。

20.回路 (Circuit)与简单回路 (Simple circuit)
- 回路或环是指从一个顶点出发,经过一系列边和顶点,最终回到出发点的路径。
- 简单回路是指没有重复边和顶点的回路。

21.图的连通性 (Connected)与连通图 (Connected graph)以及连通分量 (Connected component)
- 连通性是指图中任意两个顶点之间都存在一条路径。
- 连通图是指图中任意两个顶点都是连通的。
- 连通分量是指在一个图中,所有连通顶点的集合。

22.导出子图/诱导子图 (Induced subgraph):导出子图是指原图中由一组顶点和它们之间的边组成的子图,而诱导子图是指原图中由一组顶点所形成的子图及其所有相邻边。

23.补图:补图是指原图的所有顶点以及原图中没有的边组成的图。

24.一些特殊的无向简单图
- 星图:一个中心顶点和其余顶点连接而成的图。
- 圈图:一个闭合的顶点序列,每个顶点都与其他顶点相连。

25.无向简单图有关的二元运算(交、并、和、笛卡尔积)

- 交(Intersection):图G和H的交是由G和H中共同的边组成的图。如果两条边在G和H中都存在,那么它们也存在于交图中。
- 并(Union):图G和H的并是由G和H中的所有边组成的图,包括G中的边和H中的边,但不包括G和H的交中的边。
- 和(Symmetric Difference):图G和H的和是由G和H中不共同的边组成的图。如果一条边在G中但不在H中,或者在H中但不在G中,那么这条边就在和图中。
- 笛卡尔积(Cartesian Product):图G和H的笛卡尔积是由G的每个顶点与H的每个顶点相连组成的图。如果G有v个顶点,H有w个顶点,那么G和H的笛卡尔积有vw个顶点,每个顶点都是由一个来自G的顶点和一个来自H的顶点组成的。

26.点割集与边割集
- 点割集:如果移除图中的一个顶点,会导致原图不再连通,那么这个顶点就是一个点割。所有这样的顶点的集合称为点割集。
- 边割集:如果移除图中的一条边会导致原图不再连通,那么这条边就是一个边割。所有这样的边的集合称为边割集。

27.树、森林、最小生成树
- 树是一种没有环的无向图,它是连通的,并且有n个顶点就有n-1条边。
- 森林是由零个或多个树组成的图。
- 最小生成树是指在一个加权连通图中,权值之和最小的生成树。

28.最短路径
- 最短路径是指在加权图中,连接两个顶点的路径中权值之和最小的路径。

29.拓扑排序
- 拓扑排序是指对有向无环图(DAG)的所有顶点进行排序,使得对于图中的每条有向边(u,v),顶点u在排序中顶点v之前。这样的排序是唯一的,如果存在多个DAG可以有多个拓扑排序。

2.图的存储

2.1.直接存法

使用一个数组来存边,数组中的每个元素都包含一条边的起点与终点(带边权的图还包含边权)(或者使用多个数组分别存起点,终点和边权)。空间复杂度:O(m)。

struct Edge {
  int u, v;
};
vector<Edge> e;

 1.查询是否存在某条边

struct Edge {
  int u, v;
};
vector<Edge> e;
int m;//有m条边
bool find_edge(int u, int v) {
  for (int i = 1; i <= m; i++) {
    if (e[i].u == u && e[i].v == v) {
      return true;
    }
  }
  return false;
}

算法复杂度为:O(m);

2.遍历一个点的所有出边

struct Edge {
  int u, v;
};
vector<Edge> e;
int m;//有m条边
void find_outedge(int u) {
  for (int i = 1; i <= m; i++) {
    if (e[i].u == u) {
      //对这个点的出边的操作
    }
  }
}

算法复杂度:O(m);

3..遍历整个图

struct Edge {
  int u, v;
};
vector<Edge> e;
int m, n;//m条边,n个点
vector<bool> vis(n + 1, false);
void dfs(int u) {
  if (vis[u]) return;//访问过返回
  vis[u] = true;//u访问过
  for (int i = 1; i <= m; i++) {
    if (e[i].u == u) {
      dfs(e[i].v);//递归遍历下一个节点
    }
  }
}

算法复杂度:O(nm);

应用

由于直接存边的遍历效率低下,一般不用于遍历图。

在 Kruskal 算法 Kruskal 算法中,由于需要将边按边权排序,需要直接存边。

在有的题目中,需要多次建图(如建一遍原图,建一遍反图),此时既可以使用多个其它数据结构来同时存储多张图,也可以将边直接存下来,需要重新建图时利用直接存下的边来建图。

2.2.邻接矩阵

使用一个二维数组 adj 来存边,其中 adj[u][v] 为 1 表示存在u到v的边,为 0 表示不存在。如果是带边权的图,可以在 adj[u][v] 中存储u到b的边的边权。空间复杂度:O(n^{2}) 。

vector<vector<bool> > adj;

 1.查询是否存在某条边

vector<vector<bool> > adj;
bool find_edge(int u, int v) { return adj[u][v]; }

算法复杂度为:O(1);

2.遍历一个点的所有出边

struct Edge {
  int u, v;
};
vector<vector<bool> > adj;
int n;//有n个点
void find_outedge(int u) {
  for (int i = 1; i <= n; i++) {
    if (adj[u][n]) {
      //对这个点的出边的操作
    }
  }
}

算法复杂度:O(n);

3..遍历整个图

int m, n;//m条边,n个点
vector<bool> vis(n + 1, false);
vector<vector<bool> > adj;
void dfs(int u) {
  if (vis[u]) return;//访问过返回
  vis[u] = true;//u访问过
  for (int v = 1; v <= n; i++) {
    if (adj[u][v]) {
      dfs(v);//递归遍历下一个节点
    }
  }
}

算法复杂度:O(n^{2});

应用

邻接矩阵只适用于没有重边(或重边可以忽略)的情况。

其最显著的优点是可以O(1)查询一条边是否存在。

由于邻接矩阵在稀疏图上效率很低(尤其是在点数较多的图上,空间无法承受),所以一般只会在稠密图上使用邻接矩阵。

2.3.邻接表

使用一个支持动态增加元素的数据结构构成的数组,如 vector<int> adj[n + 1] 来存边,其中 adj[u] 存储的是点u的所有出边的相关信息(终点、边权等)。空间复杂度:O(m)。用d^{+}(v)代指点v的出度,即以v为出发点的边数。

vector<vector<int> > adj;//以存终边为例 

 1.查询是否存在某条边

vector<vector<int> > adj;//以存终边为例 
bool find_edge(int u, int v) {
  for (int i = 0; i < adj[u].size(); i++) {
    if (adj[u][i] == v) {
      return true;
    }
  }
  return false;
}

算法复杂度为:O(d^{+}(v));(如果事先进行了排序就可以使用二分查找做到O(log(d^{+}(v)))。

2.遍历一个点的所有出边

vector<vector<int> > adj;//以存终边为例 
void find_outedge(int u) {
  for (int i = 0; i < adj[u].size(); i++) {
    adj[u][i]//对这个点的出边的操作
  }
}

算法复杂度:O(d^{+}(v));

3..遍历整个图

int m, n;//m条边,n个点
vector<bool> vis(n + 1, false);
vector<vector<int> > adj;
void dfs(int u) {
  if (vis[u]) return;//访问过返回
  vis[u] = true;//u访问过
  for (int i = 0; i < adj[u].size(); i++) dfs(adj[u][i]);//递归遍历下一个节点
}

算法复杂度:O(n + m);

应用

存各种图都很适合,除非有特殊需求(如需要快速查询一条边是否存在,且点数较少,可以使用邻接矩阵)。

尤其适用于需要对一个点的所有出边进行排序的场合。

2.4.链式前向星

本质上是用链表实现的邻接表,核心代码如下:

// head[u] 和 cnt 的初始值都为 -1
void add(int u, int v) {
  nxt[++cnt] = head[u];  // 当前边的后继
  head[u] = cnt;         // 起点 u 的第一条边
  to[cnt] = v;           // 当前边的终点
}
// 遍历 u 的出边
for (int i = head[u]; i != -1; i = nxt[i]) {
  int v = to[i];
}
#include <iostream>
#include <vector>

using namespace std;

int n, m;
vector<bool> vis;
vector<int> head, nxt, to;

void add(int u, int v) {
  nxt.push_back(head[u]);
  head[u] = to.size();
  to.push_back(v);
}

bool find_edge(int u, int v) {
  for (int i = head[u]; i != -1; i = nxt[i]) {  
    if (to[i] == v) {
      return true;
    }
  }
  return false;
}

void dfs(int u) {
  if (vis[u]) return;
  vis[u] = true;
  for (int i = head[u]; i != -1; i = nxt[i]) dfs(to[i]);
}

int main() {
  cin >> n >> m;

  vis.resize(n + 1, false);
  head.resize(n + 1, -1);

  for (int i = 1; i <= m; ++i) {
    int u, v;
    cin >> u >> v;
    add(u, v);
  }

  return 0;
}

各个算法复杂度与邻接矩阵相同

应用

存各种图都很适合,但不能快速查询一条边是否存在,也不能方便地对一个点的出边进行排序。

优点是边是带编号的,有时会非常有用,而且如果 cnt 的初始值为奇数,存双向边时 i ^ 1 即是 i 的反边(常用于网络流)。

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

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

相关文章

数据库不应放在容器中?- B站Kubernetes有状态服务实践(Elasticsearch/Clickhouse)

本期作者 前言 云原生时代下&#xff0c; Kubernetes已成为容器技术的事实标准&#xff0c; 使得基础设施领域应用下自动化运维管理与编排成为可能。对于无状态服务而言&#xff0c; 业界早已落地数套成熟且较完美的解决方案。可对于有状态的服务&#xff0c; 方案的复杂度就以…

Spring Cloud Alibaba微服务从入门到进阶(一)

Springboot三板斧 1、加依赖 2、写注解 3、写配置 Spring Boot Actuator Spring Boot Actuator 是 Spring Boot 提供的一系列用于监控和管理应用程序的工具和服务。 SpringBoot导航端点 其中localhost:8080/actuator/health是健康检查端点&#xff0c;加上以下配置&#xf…

关于yolov8文档的记录,补充一些整理的知识点

2023年由Ultralytics 提供了YOLOv8开源项目。YOLOv8 支持全方位的视觉 AI 任务&#xff0c;包括检测、分割、姿态估计、跟踪和分类。这种多功能性使用户能够在各种应用和领域中利用YOLOv8 的功能。安装yolov8开源项目 pip install githttps://github.com/ultralytics/ultralyti…

什么是防静电晶圆隔离膜?一分钟让你了解抗静电晶圆隔离纸

防静电晶圆隔离膜&#xff0c;也被称为防静电蓄积纸、硅片纸、半导体晶圆盒内缓冲垫片等多种名称&#xff0c;是半导体制造和运输过程中的一种重要辅助材料。 该隔离膜具备多种特性&#xff0c;如防静电、无尘、不掉屑、强韧耐用等&#xff0c;这些特性使其在半导体制造和运输中…

YOLOv8改进 | 注意力机制 | 添加YOLO-Face提出的SEAM注意力机制优化物体遮挡检测(附代码 + 修改教程)

一、本文介绍 本文给大家带来的改进机制是由YOLO-Face提出能够改善物体遮挡检测的注意力机制SEAM,SEAM(Spatially Enhanced Attention Module)注意力网络模块旨在补偿被遮挡面部的响应损失,通过增强未遮挡面部的响应来实现这一目标,其希望通过学习遮挡面和未遮挡面之间的…

腾轩科技传媒讲解百度百科词条品牌怎么创建?

品牌百度百科是为企业或个人创建的一个专门展示品牌信息、活动、产品等内容的百度百科页面。通过品牌百度百科&#xff0c;企业可以向用户展示其核心价值、产品特色&#xff0c;提升品牌知名度&#xff0c;并在互联网上建立一个权威的品牌形象。本文腾轩科技传媒讲解百度百科词…

VMware Workstation Pro17 详细安装步骤

VMware Workstation&#xff08;中文名“威睿工作站”&#xff09;是一款功能强大的桌面虚拟计算机软件&#xff0c;提供用户可在单一的桌面上同时运行不同的操作系统&#xff0c;和进行开发、测试 、部署新的应用程序的最佳解决方案。VMware Workstation可在一部实体机器上模拟…

力扣--动态规划/深度优先算法/回溯算法93.复原IP地址

这题主要用了动态规划和回溯算法。 动态规划数组初始化&#xff08;DP数组&#xff09;: 首先&#xff0c;创建一个二维数组dp&#xff0c;用于记录字符串中哪些部分是合法的IP地址。对字符串进行遍历&#xff0c;同时考虑每个可能的IP地址部分&#xff08;每部分由1到3个字符组…

Android中ANR机制

Android中的ANR分为两种&#xff0c;前台ANR和后台ANR。 前台ANR&#xff0c;是指ANR时对用户可感知&#xff0c;比如拥有当前前台可见的activity的进程&#xff0c;或者拥有前台通知的fg-service的进程&#xff0c;这些是用户可感知的场景。前台ANR&#xff0c;会出现一个系统…

岩土工程监测中振弦采集仪的选型指南与市场概况

岩土工程监测中振弦采集仪的选型指南与市场概况 振弦采集仪是岩土工程监测中常用的一种设备&#xff0c;用于测量土体的振动特性。它的选型指南和市场概况如下&#xff1a; 选型指南&#xff1a; 1. 测量参数&#xff1a;振弦采集仪可用于测量土体的振动振幅、频率、相位等参数…

Android中单例模式正确实现方式

1. 饿汉模式 -线程安全 在类加载时进行实例化&#xff0c; 线程安全&#xff0c;但会导致类加载时间变长。饿汉模式如果使用过多&#xff0c;可能会对App启动耗时带来不利影响。 2. 懒汉模式 -线程不安全 没有加锁&#xff0c; 因此线程不安全。 3. 两次判空 加同步锁 -线程不…

go语言基础 -- goroutine与管道

go协程特点 一个线程上可以起多个goroutine&#xff0c;goroutine有以下特点&#xff1a; 有独立的栈空间共享程序堆空间调度由用户控制 下面是一个简单的协程使用案例&#xff1a; package main import("fmt""strconv" )func test() {for i : 0; i &l…

18-任务管理常用API函数

任务挂起函数 void vTaskSuspend(TaskHandle_t xTaskToSuspend) void vTaskSuspendAll(void)——挂起所有任务 其实就是将调度器锁定&#xff0c;直白点挂起所有的任务&#xff0c;就是挂起任务调度器&#xff0c;调度器被挂起后&#xff0c;就不可以进行上下文的切换&#xf…

java中数组的定义与使用

Java中的数组跟c语言的数组几乎不一样&#xff0c;我们要区分对待。在之后你就能理解到我为什么说这句话了。 1.java中数组的创建与初始化 数组的创建 如下&#xff0c;皆为数组的创建。 double[] a; int[] b; 创建时的[]里面绝对不能填数字。 数组的初始化 主要分为动态…

【Python】一文带你了解如何获取 Python模块 安装路径

【Python】一文带你了解如何获取 Python模块 安装路径 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订阅…

MyBatis进阶篇

MyBatis MyBtias工具类参数入参参数是单个参数参数是多个参数入参是POJO对象入参是Map类型 自动主键增长#{}和${}两种获取参数方式结果映射动态SQLMyBatis多表查询MyBatis注解开发 MyBtias工具类 SessionUtils.java import org.apache.ibatis.io.Resources; import org.apache…

当HR问你:“什么事会让你有成就感”你该怎么回答?【文章底部添加进大学生就业交流群】

当HR问你“什么事会让你有成就感”时&#xff0c;你可以通过以下方式回答&#xff1a; 强调目标实现&#xff1a; 表达你在达成挑战性目标时感到的满足感。举例说明你在过去的工作或项目中如何设定并成功实现了目标。 强调对团队成功的贡献&#xff1a; 谈论你与团队合作取得成…

力扣每日一题 将标题首字母大写 模拟 String API

Problem: 2129. 将标题首字母大写 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 灵神题解 复杂度 ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public String capitalizeTitle(String title)…

leetcode 25、k个一组翻转链表

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

C++程序设计-练手题集合【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下C程序设计中的练手题&#xff0c;以供大家期末复习和考研复习的时候使用。 C程序设计系列文章传送门&#xff1a; 第一章 面向对象基础 第四/五章 函数和类和对象 第六/七/八章 运算符重载/包含与继承/虚函数…