首页 > 编程语言 >C++U7-06-图的进阶存储

C++U7-06-图的进阶存储

时间:2024-05-26 11:12:56浏览次数:15  
标签:06 进阶 int U7 数组 邻接 链式 顶点 前向星

上节课作业讲解:

链接:https://pan.baidu.com/s/1A3Y5_12IgwYbmuep0Q2w6Q?pwd=0000
提取码:0000

 

 

邻接表和链式前向星都是图论中用于表示图的常用数据结构,它们各自有特定的特点和用途。以下是对这两种数据结构的详细解释:

邻接表

定义与特点:

  • 邻接表是用来表示有限图的无序列表的集合,每个列表描述了图中相邻顶点的集合。
  • 邻接表是计算机程序中几种常用图的表示法之一,特别是在需要存储大型图时。
  • 邻接表是一种顺序分配和链式分配相结合的存储结构。如果某个顶点存在相邻顶点,则把相邻顶点依次存放于该顶点所指向的单向链表中。
  • 对于无向图,使用邻接表进行存储会出现数据冗余,因为无向图中的边是双向的,所以每个边会在两个顶点的邻接表中各出现一次。
  • 邻接表通常用于表示稀疏图,因为它可以节省存储空间。

实现细节:

  • 在邻接表中,图的每个顶点都与一个链表相关联,链表中的每个节点表示与该顶点相邻的一个顶点。
  • 邻接表可以用数组和链表来实现,其中数组用于存储顶点,链表用于存储与每个顶点相邻的顶点。
  • 邻接表的一个变体是使用散列表(哈希表)将图中的每个顶点与相邻顶点的数组做关联,这种实现方法中没有将边明确表示为对象。

数字信息:

  • 对于一个具有n个顶点和e条边的无向图,邻接表表示中会有n个顶点表结点和2e个边表结点(因为每条边在邻接表中会出现两次)。
  • 对于有向图,邻接表表示中会有n个顶点表结点和e个边表结点(因为有向图是单向的)。

链式前向星

定义与特点:

  • 链式前向星是一种特殊的边集数组,与邻接表的思想相似,但实现方式略有不同。
  • 链式前向星使用结构体数组来实现,是静态的,需要在一开始就知道数据范围并开好数组大小。
  • 链式前向星避免了邻接表在添加边时可能需要的动态内存分配,因此在某些情况下可能更加高效。

实现细节:

  • 链式前向星中,边被存储在一个结构体数组中,每个结构体包含边的终点、下一条同起点边的索引以及边的权值(如果有的话)。
  • 通过一个额外的数组(通常称为head数组)来记录每个顶点作为起点时的第一条边的索引。
  • 添加边时,只需要在结构体数组中分配一个新的位置,并更新head数组和相应边的next指针。

与邻接表的比较:

  • 邻接表更加灵活,可以动态地增加边,而链式前向星则需要在一开始就知道数据范围。
  • 链式前向星在内存使用上可能更加紧凑,因为它避免了邻接表中可能出现的链表指针的空间开销。
  • 在实现上,链式前向星通常比邻接表更加直观和易于理解,因为它直接使用数组来存储边和顶点信息。

总结来说,邻接表和链式前向星都是用于表示图的有效数据结构,它们各有优缺点,适用于不同的场景和需求。在选择使用哪种数据结构时,需要根据具体的应用场景和性能要求来进行权衡。

 

 

 复习图

 

 邻接表存图

 

 

 链式前向星的存图方式

 过程如果忘了就问问老师

链式前向星存图构建代码

 

[【图的存储】有向图的权重]

 邻接表和链式前向星两种方式代码

【算法分析】
用邻接表将图存储,然后以枚举每个点,将从每个点开始的边的权值进行相加。

【参考代码】
//vector数组
#include<bits/stdc++.h>
using namespace std;

struct node {
    int v, w;
};
vector<node> ve[109];
int main() {
    int n, m;
    cin >> n >> m;
    while (m--) {
        int u, v, w;
        cin >> u >> v >> w;
        ve[u].push_back({ v,w });
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < ve[i].size(); j++) {
            ans += ve[i][j].w;
        }
    }
    cout << ans;
    return 0;
}

//链式前向星
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
struct node {
    int to; // 终点
    int next; // 下一个位置
    int w; // 权重
} edge[N]; // 边结构体数组
int head[N]; // 链表数组,顶点链表起始位置
int cnt; // 当前的已加入的边数
// 插入一条新边,起点为 u
void add(int u, int v, int w) {
    // 表示新边的结点
    edge[++cnt].to = v;
    edge[cnt].w = w;
    // 新结点指向 u 的链表的链头
    edge[cnt].next = head[u];
    // 新结点作为新的链头
    head[u] = cnt;
}
int main() {
    int n, m;
    cin >> n >> m;
    while (m--) {
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w); // 添加边
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = head[i]; j; j = edge[j].next) {
            ans += edge[j].w;
        }
    }
    cout << ans;
    return 0;
}
View Code

 

 

 

[【图的存储】公路查询]

 

【算法分析】
用邻接表将图存储。如果采用 vector 数组存图,由于题目要求后记录的边先输出,因此需要逆序遍历。链式前向星本身就是后记录的边再前面。

【参考代码】
//vector数组
#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
struct node {
    int v, w;
};
vector<node> ve[maxn];
int main() {
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        ve[u].push_back({ v,w });
    }
    while (q--) {
        int x;
        cin >> x;
        for (int i = (int)ve[x].size() - 1; i >= 0; i--) {
            cout << ve[x][i].v << " " << ve[x][i].w << '\n';
        }
    }
    return 0;
}

//链式前向星
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
struct node {
    int to; // 终点
    int next; // 下一个位置
    int w; // 权重
} edge[N]; // 边结构体数组
int head[N]; // 链表数组,顶点链表起始位置
int cnt; // 当前的已加入的边数
// 插入一条新边,起点为 u
void add(int u, int v, int w) {
    // 表示新边的结点
    edge[++cnt].to = v;
    edge[cnt].w = w;
    // 新结点指向 u 的链表的链头
    edge[cnt].next = head[u];
    // 新结点作为新的链头
    head[u] = cnt;
}
int main() {
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w); // 添加边
    }
    while (q--) {
        int x;
        cin >> x;
        for (int j = head[x]; j; j = edge[j].next) {
            cout << edge[j].to << " " << edge[j].w << '\n';
        }
    }
    return 0;
}
View Code

 

作业讲解:

链接:https://pan.baidu.com/s/1eVLnEcN3HOAK4tL_iIZiGQ?pwd=0000
提取码:0000

 

标签:06,进阶,int,U7,数组,邻接,链式,顶点,前向星
From: https://www.cnblogs.com/jayxuan/p/18212637

相关文章

  • hduoj 1506(笛卡尔树)
    Problem-1506(hdu.edu.cn)题意坐标轴给定一些矩形,紧密排在一起,每个矩形宽度固定为1,问形成的图案中最大可以组成的矩形面积。思路常规思路是可以用单调栈分别找两边的合法边界,这里使用笛卡尔树。笛卡尔树实现了堆的性质,并且对原数组建立的笛卡尔树进行中序遍历为原数组的顺......
  • 【Python进阶】轻松上手,6种打包Python代码的方法,让你的程序变成exe应用!
    Python是一种高级编程语言,它具有易学易用、跨平台等优点,因此在开发中得到了广泛的应用。然而,Python代码需要在Python解释器中运行,这对于一些用户来说可能不太方便。因此,将Python代码打包成可执行文件(exe)是一种很好的解决方案。本文将介绍6种将Python代码打包成exe应用的方......
  • Android14音频进阶之AAOS之CarAudioService如何衔接AudioControl服务(七十四)
    简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】......
  • ASE60P06-ASEMI场效应MOS管ASE60P06
    编辑:llASE60P06-ASEMI场效应MOS管ASE60P06型号:ASE60P06品牌:ASEMI封装:TO-220批号:2024+沟道:N沟道导通内阻RDS(ON)Max:19mΩ启动电压:2V-4V最大漏源电流(Id):60A漏源击穿电压(VRM):60V安装方式:直插式封装正向电压:1.3V特性:低压N沟道MOS管产品引线数量:3产品内部芯片个数:2产品内部......
  • MyBatis进阶
    时间:2024-05-25星期五MyBatis高级特性MyBatis日志管理日志日志文件是用于记录系统操作事件的记录文件或文件集合日志保存历史数据,使诊断问题以及理解系统活动的重要依据SLF4J与Logback日志组件关系 SLF4j作为日志输出的门面,负责日志输出的表现;logback是对日志......
  • 【爆肝分享】AI绘图Stable Diffusion-ComfyUI 从入门到精通完整学习教程资料,AI绘图高
    「前言」自从2022年stablediffusion横空出世以来,AI绘图正以其强大的表现能力与惊人的迭代速度极大的改变了建筑师设计与表现的工作流程。无论是利用AI的随机性与可控性进行项目构思。▲AI体块造型构思亦或是利用AI辅助建筑表现。▲AI线稿精准控图甚至使用AI进行......
  • SpringMVC进阶-02
    1.请求和响应中多次获取流中数据异常处理SpringMVC请求流中数据只能被使用一次,如果多次使用就会产生异常。如果使用了Post请求传送数据,在DispatcherServlet中doDispatch()中会将数据转换为controller中@RequestBody注解需要的数据,此时使用HttpServletRequest.getInputStream(......
  • 春秋CVE-2022-23906
    简介CMSMadeSimplev2.2.15被发现包含通过上传图片功能的远程命令执行(RCE)漏洞。此漏洞通过精心制作的图像文件被利用。正文1.进入靶场2.进入登录界面,弱口令admin/1234563.进入后台,文件上传点4.上传一句话木马图片5.复制图片,后缀改为php6.蚁剑连接7.得到flag......
  • Day3 | 203.移除链表元素 、707.设计链表 、 206.反转链表
    203.移除链表元素建议:本题最关键是要理解虚拟头结点的使用技巧,这个对链表题目很重要。题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.移除链表元素.html思考设置一个虚拟的dummy节点,方便代码逻辑一致,不然要专门处理头节点。定义一个pre节点,作为cur节点的前驱......
  • Java面试进阶指南:高级知识点问答精粹(二)
    Java面试问题及答案1.什么是Java内存模型(JMM)?它在并发编程中扮演什么角色?答案:Java内存模型(JMM)是一个抽象的模型,它定义了Java程序中各种变量(线程共享变量)的访问规则,以及在并发环境下这些变量如何被不同线程所看到。JMM规定了主内存和工作内存的概念,以及它们之间的交互规......