图论(二)-图的建立

引言: 建图,将图放进内存的方法

            常用的建图方式:邻接矩阵,邻接链表,链式前向星    

一、邻接矩阵

                通过一个二维数组即可将图建立,邻接矩阵,考虑节点集合 V=\left \{ 1,2,3......n \right \} ,用一个二维数组定义邻接矩阵A\left [ 1.....n \right ]\left [ 1.....n \right ],满足以下

对于一个简单的有向图(或无向图),邻接矩阵如下:

    无向图:若 u 与 v 之间存在一条边,则 A[u][v]=A[v][u]=1 (两个方向)

    有向图:若有一条 u 指向 v 的边,则 A[u][v]=1;若有一条 v 指向 u 的边,则 A[v][u]=1(单向)

       邻接矩阵的空间消耗为O(V^{2}),无向图的邻接矩阵为对称矩阵。在某些情况下,只存储邻接矩阵的对角线及以上的部分,这样,图占用的存储空间可以减少一半。

二、邻接链表(vector建表)

       Adj为一个包含 V 条链表的数组,每个节点有一个链表,对于每个节点u∈V,邻接链表Adj[u]包含所有与节点u之间有边相连的节点v。

        如果G是一个有向图,则对于边(u,v)而言,节点 v 将出现在链表 Adj [ u ]里,所有邻接链表的长度之和等于 E;如果G是一个无向图,对于边(u,v),节点v将出现在链表 Adj [ u ] 里,节点 u 将出现在链表 Adj [ v ]里,所有邻接链表的长度之和为 2*E。

         对一个有向图通过vector建图:

        建图过程: 

            用结构体 node 存储两个数据(终点编号,边权值),建立 node 型的 vector 动态数组。建图也只需要将 结构体 直接插入 vector动态数组 末端即可。


typedef struct Node{int v;  //终点编号int w;  //起点到终点的边权
}Node;
vector<Node> map[201];    //用 vector 建立(不是严格意义上的链表)
void get_map(int m)
{for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);Node tmp;tmp.v=v;tmp.w=w;map[u].push_back(tmp);    //将 终点节点v 和 边权w 加入 节点u 的链表末尾tmp.v=u;tmp.w=w;    //如果为无向图,反向边map[v].push_back(tmp);   // 将 将终点节点u 和边权w 加入 节点v 的链表末尾}
}

        邻接链表表示法的储存空间均为 O(V+E)

        vector 数组建图的应用(使用):

        最小生成树prim算法(完整代码):

#include<stdio.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string.h>
#include<stdlib.h>
using namespace std;
struct node{int w;int v;friend bool operator<(node x,node y){ return x.w>y.w;} // 优先队列比较 按照w从小到大排?? 
};
priority_queue<node>q; // 建立数据类型为node结构体的优先队列 
int n,m,dis[1001],vis[1001];
vector<node>map[1001]; // 以node结构体的 vector数组 
int sum=0;
void prim(int s)
{memset(dis,0x3f,sizeof(dis)); // 初始化 memset(vis,0,sizeof(vis));dis[s]=0;q.push((node){0,s});while(!q.empty()){int u=q.top().v;q.pop();if(vis[u]) continue;vis[u]=1;sum+=dis[u];for(int i=0;i<map[u].size();i++) // vector建图的使用 {int v=map[u][i].v;int w=map[u][i].w;if(dis[v]>w){dis[v]=w;q.push((node){w,v});}}}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);node tmp; // vector 建图 tmp.v=v;tmp.w=w;map[u].push_back(tmp);tmp.v=u; map[v].push_back(tmp); // 反向边 }prim(1);for(int i=1;i<=n;i++) {if(!vis[i]) {printf("orz");return 0;}}printf("%d",sum);return 0; }

三、链式前向星

             链式前向星所用结构体和相关变量,建图函数

struct node{int to,next,w;
}edge[2001];
int head[1001];
int cnt=0;
void addedge(int u,int v,int w)
{edge[++cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt;
}

        初始化函数

//初始化函数
void init()
{memset(head,-1,sizeof(head));    //将head数组的值全置为-1.cnt=0;//初始化边的编号
}

对于一个有向图,用链式前向星建图: 

        关于结构体中 next 数组含义: 某一条边的起点连接的上一个编号比它小的边由于初始化,当某条边的next值为 -1 时,此条边为最后一条边。

 运用链式前向星遍历图的过程:

        首先根据节点 u 找到以 u 为起始点的边的编号,然后根据 next 找到下一条以 u 为起始点的边的编号,以此类推。

        以链式前向星的方法建图的最小生成树prim算法: (主要代码)

void addedge(int u,int v,int w)
{edge[++cnt].v=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt;
}
void prim(int s)
{memset(dis,0x3f,sizeof(dis)); // 初始化 memset(vis,0,sizeof(vis));dis[s]=0;q.push((node1){0,s});while(!q.empty()){int u=q.top().v;q.pop();if(vis[u]) continue;vis[u]=1;sum+=dis[u];for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;int w=edge[i].w;if(dis[v]>w){dis[v]=w;q.push((node1){w,v});}}}
}

四、三种方法的优缺点比较::

        1.邻接矩阵:

            邻接矩阵通过一个二维数组直接表示两点之间的权值,但是由于二维数组,容易出现空间空间的浪费,并且数据量大时会出现爆栈。

        2. 邻接链表(vector):

            通过STL,步骤简单,vector采用可变数组的方式,动态变化时会耗费额外时间复制数组。

        3.链式前向星:

           操作简单,但不容易理解。

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

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

相关文章

迭代器模式(行为型)

目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为&#xff0c;抽象出…

gcc -m32 一堆报错:No such file or directory

问题&#xff1a;终端执行命令gcc -m32 *.c -o xxx.so 出现一堆缺失文件的报错。 解决办法&#xff1a;库没装全&#xff0c;终端执行下面的命令。 sudo apt install gcc-multilib

【设计模式】JAVA Design Patterns——Command(事务模式)

&#x1f50d;目的 将请求封装为对象&#xff0c;从而使你可以将具有不同请求的客户端参数化&#xff0c;队列或记录请求&#xff0c;并且支持可撤销操作。 &#x1f50d;解释 真实世界例子 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小&#xff0…

LabVIEW步开发进电机的串口控制程序

LabVIEW步开发进电机的串口控制程序 为了提高电机控制的精确度和自动化程度&#xff0c;开发一种基于LabVIEW的实时、自动化电机串口控制程序。利用LabVIEW软件的图形化编程特性&#xff0c;通过串口实时控制电机的运行参数&#xff0c;实现电机性能的精准控制与评估。 系统组…

nginx+nginx-http-flv-module在Linux服务器搭建

需求 在服务器搭建点播/视频平台的话需要在服务器搭建nginx和rtmp模块 rtmp模块 rtmp 模块有 nginx-rtmp-module &#xff0c;但是我们这里使用 nginx-http-flv-module 来替代。因为后者是基于前者开发的&#xff0c;前者拥有的功能后者都有&#xff0c;后者是国内的开发开…

基于PostGIS的mvt动态矢量切片的后台地图服务和前端调用

目录 一、背景 二、矢量切片 三、Mapbox的矢量切片格式 四、PostGIS生成矢量切片 ST_AsMVT: ST_AsMVTGeom: 五、导入试验数据 六、编写PostGIS函数 七:Java后端实现 八、Openlayers前端调用 一、背景 矢量切片技术目前已成为互联网地图的主流技术,无论是Mapbox还…

Vue.Draggable:强大的Vue拖放组件技术探索

一、引言 随着前端技术的不断发展&#xff0c;拖放&#xff08;Drag-and-Drop&#xff09;功能已经成为许多Web应用不可或缺的一部分。Vue.js作为现代前端框架的佼佼者&#xff0c;为开发者提供了丰富的生态系统和强大的工具链。Vue.Draggable作为基于Sortable.js的Vue拖放组件…

Slash后台管理系统源码阅读笔记 后面面板中的折线图统计卡片是怎么实现的?

之前的笔记发表在博客和公众号以后&#xff0c;得到了一部分同学的喜爱的认可&#xff0c;所以今天继续。 目前这个管理系统的代码已经处理了一小部分&#xff1a; 接下来&#xff0c;我们看看第二栏那三个折线图统计卡片是怎么实现的。 这三个卡片还是使用的 antd 一行三列…

2024年电工杯高校数学建模竞赛(A题) 建模解析| 园区微电网风光储协调优化配置

问题重述及方法概述 问题1&#xff1a;各园区独立运营储能配置方案及其经济性分析 经济性分析采用成本-效益分析方法&#xff0c;计算购电量、弃风弃光电量、总供电成本和单位电量平均供电成本等指标。 问题2&#xff1a;联合园区储能配置方案及其经济性分析 经济性分析采用成…

二叉搜索树与双向链表(C++)

文章目录 1. 题目描述2.题目解析 题目来源&#xff1a; 牛客网…二叉搜索树与双向链表 1. 题目描述 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。如下图所示 数据范围&#xff1a;输入二叉树的节点数 0≤n≤1000&#xff0c;二叉树中每个节点的值…

klinecharts自定义覆盖物

import { registerFigure, registerOverlay } from "klinecharts";registerFigure({name: "custom_graphics",checkEventOn: (coordinate, attrs) => {// 当前鼠标坐标,判断事件是否可用const { x: px, y: py } = coordinate;const { x, y, r } = attr…

重生之while在鸣潮学习HTML标签

个人主页&#xff1a;终端 HTML标签 目录 2.1标题标签 2.2段落标签 2.3换行标签 2.4列表标签 2.5超链接标签 2.6图片标签 2.7表格标签 2.8-2.9表单标签&表单项 2.10布局相关标签 2.11特殊字符 2.1标题标签 标题标签 代码 <h1>鸣</h1> <h2>潮<…

高弹性架构的微服务设计模式

长期以来&#xff0c;开发人员一直使用单片架构&#xff0c;而且长期以来&#xff0c;这种架构一直有效。不幸的是&#xff0c;这些架构使用的部件较少&#xff0c;但体积较大&#xff0c;这意味着如果一个部件发生故障&#xff0c;它们更有可能整体失效。通常&#xff0c;这些…

golang session实现库 支持cookie, redis,mysql等多种存储方式

golang中官方是不支持session的&#xff0c; 如果想要实现session则需要自己动手来实现&#xff0c;或者使用第三方的go-session实现库&#xff0c; 今天就给大家介绍一个go语言的第三方session实现库 go-sessions&#xff0c;支持 的存储方式有 cookie, file, redis, mysql等众…

学习Java的日子 Day49 函数,DOM

Day48 1.流程控制语句 if else for for-in(遍历数组时&#xff0c;跟Java是否一样) While do while break 语句用于跳出循环 continue 用于跳过循环中的一个迭代 2.函数 2.1 JavaScript 函数语法 函数就是包裹在花括号中的代码块&#xff0c;前面使用了关键词 function funct…

图论(四)—最短路问题(Dijkstra)

一、最短路 概念&#xff1a;从某个点 A 到另一个点B的最短距离&#xff08;或路径&#xff09;。从点 A 到 B 可能有多条路线&#xff0c;多种距离&#xff0c;求其中最短的距离和相应路径。 最短路径分类&#xff1a; 单源最短路&#xff1a;图中的一个点到其余各点的最短路径…

(ICRA 2024) Diffusion-Based Point Cloud Super-Resolution for mmWave Radar Data

今天介绍一篇使用Diffusion模型来生成超分辨率雷达点云的方法。毫米波雷达传感器在不利的环境条件下可以保持稳定的性能&#xff0c;使其成为室外移动机器人全天候感知任务的一个有希望的解决方案。然而&#xff0c;雷达点云相对稀疏&#xff0c;包含大量鬼点&#xff0c;极大地…

【驱动】RS485收发控制、自动收发电路及波特率限制

1、芯片本身支持自动收发 RS485收发器芯片本身支持自动收发切换: 优点:简化硬件设计和软件编程,减少外部控制线;缺点:成本高,传输速率可能受限制。下面介绍几款支持自动收发切换的RS485/422芯片 1.1 MAX13487 MAX13487 是一款由 美信(Maxim) 生产的半双工 RS-485/RS…

旧衣回收小程序开发,互联网发展下的巨大商机

随着人们生活水平的提高&#xff0c;对衣物的要求也越来越高&#xff0c;因此推动了旧衣回收市场的发展&#xff0c;旧衣回收行业逐渐兴起。 而在互联网的持续发展下&#xff0c;旧衣回收行业也从传统的回收箱走向了线上旧衣回收小程序。在当下社会中&#xff0c;完善线上旧衣…

C++模版初阶STL简介

目录 1.泛型编程 2.函数模版 2.1概念 2.2格式 2.3原理 2.4函数模版的实例化 2.5模版参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 1.泛型编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int& left, int& right) {int temp left;l…