图论(二)-图的建立

news2024/11/20 6:29:55

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

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

一、邻接矩阵

                通过一个二维数组即可将图建立,邻接矩阵,考虑节点集合 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.coloradmin.cn/o/1691879.html

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

相关文章

自定义原生小程序顶部及获取胶囊信息

需求&#xff1a;我需要将某个文字或者按钮放置在小程序顶部位置 思路&#xff1a;根据获取到的顶部信息来定义我需要放的这个元素样式 * 这里我是定义某个指定页面 json&#xff1a;给指定页面的json中添加自定义设置 "navigationStyle": "custom" JS&am…

子分支想主分支发起合并请求

请求合并 1.点击 git Web 页右上角打开 Merge requests 进入新页&#xff0c;点击右上角。注意选择要合并的项目 2.左边是源分支&#xff0c;右边是要合并的目标分支。 3.最后点击左下角绿色按钮 4.第一个红框 Assignee&#xff0c;选择要通知去合并的人。第二个红框不动&#…

BUUCTF---web---[BJDCTF2020]ZJCTF,不过如此

1、点开连接&#xff0c;页面出现了提示 传入一个参数text&#xff0c;里面的内容要包括I have a dream。 构造&#xff1a;?/textI have a dream。发现页面没有显示。这里推测可能得使用伪协议 在文件包含那一行&#xff0c;我们看到了next.php的提示&#xff0c;我们尝试读取…

Pytorch-08 实战:手写数字识别

手写数字识别项目在机器学习中经常被用作入门练习&#xff0c;因为它相对简单&#xff0c;但又涵盖了许多基本的概念。这个项目可以视为机器学习中的 “Hello World”&#xff0c;因为它涉及到数据收集、特征提取、模型选择、训练和评估等机器学习中的基本步骤&#xff0c;所以…

强化学习4:DQN 算法

看这篇文章之前&#xff0c;建议先了解一下&#xff1a;Q-Learning 算法。 1. 算法介绍 DQN 算法全称为 Deep Q-Network&#xff0c;即深度Q网络。它将 Q-Learning 与 Deep Learning 结合在了一起。 1.1 Q-Network Q-Learning 是使用 Q-table 才存储决策信息的&#xff0c;…

spring常用知识点

1、拦截器和过滤器区别 1. 原理不同&#xff1a; 拦截器是基于java的反射机制&#xff0c;而过滤器采用责任链模式是基于函数回调的。 2. 使用范围不同&#xff1a; 过滤器Filter的使用依赖于Tomcat等容器&#xff0c;导致它只能在web程序中使用 拦截器是一个Sping组件&am…

IO模型:同步阻塞、同步非阻塞、同步多路复用、异步非阻塞

目录 stream和channel对比 同步、异步、阻塞、非阻塞 线程读取数据的过程 同步阻塞IO 同步非阻塞IO 同步IO多路复用 异步IO 优缺点对比 stream和channel对比 stream不会自动缓冲数据&#xff0c;channel会利用系统提供的发送缓冲区、接收缓冲区。stream仅支持阻塞API&am…

【C++】哈希和unordered系列容器

目录 一、unordered系列关联式容器的引入 二、容器使用 2.1 unordered_map的文档说明 2.2 unordered_map的使用 2.3 unordered_set 三、底层结构 3.1 哈希概念 3.2 哈希表 3.3 哈希冲突 3.4 哈希函数 3.5 哈希冲突解决 3.5.1 闭散列 3.5.2 开散列 3.5.3 思考 四…

C++ RBTree

目录 概念 性质 节点的定义 树的结构 Insert 1. pparent->_left parent 1.1 uncle && uncle->_col RED 1.2 !(uncle && uncle->_col RED) 1.2.1 parent->_left cur 1.2.2 parent->_right cur 2. pparent->_right parent …

hive3从入门到精通(一)

Hive3入门至精通(基础、部署、理论、SQL、函数、运算以及性能优化)1-14章 第1章:数据仓库基础理论 1-1.数据仓库概念 数据仓库&#xff08;英语&#xff1a;Data Warehouse&#xff0c;简称数仓、DW&#xff09;,是一个用于存储、分析、报告的数据系统。 数据仓库的目的是构…

第十六讲:数据在内存中的存储

第十六讲&#xff1a;数据在内存中的存储 1.整数在内存中的存储1.1存储方式1.2大小端字节序1.3大小端字节序排序规则1.4为什么要有大小端1.5练习1.5.1练习11.5.2练习21.5.3练习31.5.4练习41.5.5练习51.5.6练习61.5.7练习7 2.浮点数在内存中的存储2.1练习2.2浮点数的存储2.3浮点…

常见的几种数据库通过SQL对表信息进行查询

一、前言 我们查询数据库表的信息&#xff0c;一般都使用界面化的连接工具查看&#xff0c;很少使用SQL语句去查&#xff0c;而且不同的数据库SQL语句又各自有差异。但如果通过代码去获取数据库表的信息&#xff0c;这时就需要通过SQL语句去查了&#xff0c;这个在逆向代码生成…

【案例分享】医疗布草数字化管理系统:聚通宝赋能仟溪信息科技

内容概要 本文介绍了北京聚通宝科技有限公司与河南仟溪信息科技有限公司合作开发的医疗布草数字化管理系统。该系统利用物联网技术实现了医疗布草生产过程的实时监控和数据分析&#xff0c;解决了医疗布草洗涤厂面临的诸多挑战&#xff0c;包括人工记录、生产低效率和缺乏实时…

打造专业级网页排版:全方位解析专业字体家族font-family实践与全球知名字体库导览

CSS中的字体家族&#xff08;font-family&#xff09;属性用于指定文本所使用的字体系列。它允许开发者选择一种或多种字体作为备选&#xff0c;确保在浏览器中以最佳可用字体显示文本。本文将深度解析专业级网页排版中字体家族&#xff08;font-family&#xff09;设置的实践技…

掌握Python基本语法的终极指南【基本语法部分】

一、基本语法部分 1.简单数据类型 1.1字符串类型及操作 字符串访问&#xff1a; 1.索引访问 mystr"Hello world" #索引访问 print(mystr[0]) #H print(mystr[-1]) #d print(mystr[-7]) #o print(mystr[6]) #w 2.切片访问 [头下标&#xff1a;尾下标] &#x…

车灯合面合壳密封使用UV胶的优缺点是什么呢?汽车车灯的灯罩如果破损破裂破洞了要怎么修复?

车灯合面合壳密封使用UV胶的优缺点是什么呢? 车灯合壳密封使用UV胶的优缺点如下&#xff1a; 优点&#xff1a; 快速固化&#xff1a;UV胶通过紫外线照射可以在短时间内迅速固化&#xff0c;大大缩短了车灯制造的工艺流程时间&#xff0c;提高了生产效率。高度透明&#xff…

SVG批量转为pdf超有效的方式!

最近在整理工作&#xff0c;发现ppt里面画的图智能导出svg格式无法导出pdf格式&#xff0c;由于在线的网站会把我的图片搞乱而且不想下载visio&#xff08;会把本地的word搞坏&#xff09;&#xff0c;因此琢磨出这种批量转换的方式。 1. 下载并安装Inkscape 下载链接&#xf…

基于Matlab完整版孤立词识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 孤立词识别是语音识别领域的一个重要分支&#xff0c;其目标是将输入的语音信号转换为计算机可…

成都爱尔眼科医院《中、欧国际近视手术大数据白皮书2.0》解读会圆满举行

2024年5月12日&#xff0c;爱尔眼科联合中国健康促进基金会健康传播与促进专项基金、新华社新媒体中心与中南大学爱尔眼科研究院、爱尔数字眼科研究所重磅发布《中、欧国际近视手术大数据白皮书2.0》。这是继2021、2022年在国内相继发布《国人近视手术白皮书》、《2022中、欧近…

C++笔试强训day32

目录 1.素数回文 2.活动安排 3.合唱团 1.素数回文 链接https://www.nowcoder.com/practice/d638855898fb4d22bc0ae9314fed956f?tpId290&tqId39945&ru/exam/oj 现将其转化为回文数&#xff08;这里用字符串存储比较方便转化&#xff09;&#xff0c;然后判断是否为…