C++数据结构-图的存储及邻接矩阵的代码实现

news2024/10/22 12:45:30

1. 什么是图

图论(graph theory) 是数学的一个分支,它以 图 为研究的对象。

图论本身是应用数学的一部分,历史上图论曾经被很多数学家各自独立建立过。关于图论的最早文字记载最早出现在欧拉 1736 年的论著中,也就是著名的柯尼斯堡(Konigsberg)问题(七桥问题)。

2. 图的定义

一个图G是一个二元组,即序偶<V,E>,或记作G=<V,E> ,其中V是有限非空集合,称为G的顶点集,V中的元素称为顶点或结点;E称为 G的边的集合,所有的边ei都属于E,都有v中的结点与之对应,称ei为 G的边。

3. 图的基本概念

l  无向图:每条边都是无向边的图。

l  有向图:每条边都是有向边的图。

l  混合图:在一个图中,有些边是有向边,另一些边是无向边,则该图为混合图。

l  有限图:一个图的点集和边集都是有穷集的图。

l  零图:边集为空集的图。

l  平凡图:仅有一个结点而没有边构成的图。

l  关联:若有ei=(u,v) 且ei属于E ,则称u是和v相关联的。

l  孤立点:无边关联的点。

l  自环:若一条边所关联的两个结点重合,则称此边为自环。

l  邻接:关联于同一条边的两个点  和  称为邻接的;关联于同一个点的两条边  和  是邻接的(或相邻的)。

4.两个定理:

l  推论:在任意图中,度数为奇数的点必然有偶数个。

l  推论:即所有点入度之和等于出度之和。

(这个比较好理解,就如同问世界上的上坡多还是下坡多一样,答案是一样多)

由上面的概念可知,树或者是森林,就是一种特殊的图。

5. 最简单的存储——邻接矩阵

邻接矩阵的英文名是 adjacency matrix。它的形式是 bool adj[n][n],这里面n是节点个数,adj[i][j]表示i和j之间是否有边。

如果边有权值,也可以直接用 int adj[n][n] ,直接把边权存进去。

它的优点是可以在O(1)时间内得到一条边是否存在,缺点是需要占用O(n^2)的空间。对于一个稀疏的图(边相对于点数的平方比较少)来说,用邻接矩阵来存储的话,成本偏高。

其代码可以表示为(假设各边长度均为1):

#include<iostream>
  
using namespace std;
  
const int maxn=105;
int adj[maxn][maxn]={0};    //定义邻接矩阵
  
int x,y;    //输入两条边
int n,m;    //供输入n对边 ,m个顶点 (x,y <= m) 
  
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>x>>y;
        adj[x-1][y-1]=1;
        adj[y-1][x-1]=1;
    }
    for(int i=0;i<m;i++){
        for(int j=0;j<m;j++){
            cout<<adj[i][j]<<' ';
        }
        cout<<endl;
    }
    return 0;
}

6. 邻接表概念

邻接表(Adjacency List)顾名思义,就是通过链表或者利用数组模拟链表的方式将图的相连接关系表示的一种方法,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。

如图:

(如图为一个图关系)

例图展示了一个图状关系,结点1指向2和3,2可以指向4和5,而3指向4……这样的指向表示该图是单向的,意思是只允许1到2而不允许2到1(除非有两个箭头相互指向),那么,依据这个指向关系,可以得到邻接表如下:

(如图为该图所表示的邻接表)

这里必须要特别注意邻接表的结尾以空或者一个特殊的标记,表示到达结尾。在一些需要快速表达概念的场合,可以将空结点的指向忽略不表达。

那么如果是双向图,意思是1与2联通,可以由1走向2,同时也可以由2走向1的情况时,这张表又是如下表示

可以见的,这双向图和单向图的邻接表表达方式是不一样的,双向图还要将联通方式表达,1联通2,在1结点的连接关系中要将2结点加入以表达1能够走向2,此外还需要再2结点中将1结点加入以表达2能够走向1,这可能会稍微显得麻烦但是确是值得的代价。

具体表达就是:n个顶点e条边的无向图的邻接表表示中有n个顶点表结点和2e个边表结点。(换句话说,每条边(i,j)在邻接表 中出现两次:一次在关于i的邻接表中,另一次在关于j的邻接表中)。

观察上面两个图,连接到空结点的那一条边不算,那么双向图的边正好就是单向图的两倍。

7. 邻接表的特点

在表达邻接表的适用情况时,我们首先要与邻接矩阵进行相互比较

邻接矩阵存在以下缺点

a) 浪费空间—— 存稀疏图(点很多而边很少)有大量无效元素

b) 浪费时间—— 统计稀疏图中一共有多少条边

恨明显,使用矩阵的方式,仅仅是让我们人类更加直观的观察图的关系而已,对于稀疏图(即结点很多但是边很少的图,或者表达为弱连接图)而言时间和空间的浪费还是很大的,邻接表就相当于是一种改良,对于稀疏图能够很好的适应,使用较少的空间和时间就能表达。

在常规情况下,邻接表是O(n+e)的复杂程度(n表示节点数,e表示边长),临界矩阵则是O(n^2)的复杂程度。

8. 代码构成

设计思路并不唯一,甚至你可以利用结构体数组进行模拟,本代码仅提供一份适用指针的单向图C++设计代码,思路是:将节点的adjvex赋值为v,指向下一条边的指针赋值为NULL输入之后判断图中的起始顶点指向的第一条边的指针是否为空假如为空那么将当前顶点的firstarc指针指向这个节点加入不为空那么调用插入到链表中的insertNode方法,遍历链表将节点插入到链表的最后面。

#include<stdio.h>
#include<iostream>
#include<malloc.h>
#define maxSize 1000         
using namespace std;
typedef struct ArcNode {
    int adjvex;
    struct ArcNode *nextarc;
} ArcNode;
  
typedef struct {
    int data;
    ArcNode *firstarc;
} Vnode;
  
//可以利用结构体整体结构,也可以拆分结构体变为单独搜索
typedef struct {
    Vnode adjlist[maxSize];
    int n, e;
} AGraph;
  
AGraph *graph;
  
//插入链表末尾
void  insertNode(ArcNode *node, ArcNode *newNode) {
    ArcNode *p = node;
    while(p->nextarc != NULL) {
        p = p->nextarc;
    }
    p->nextarc = newNode;
}
  
void create() {
    graph = (AGraph*)malloc(sizeof(AGraph));
    cout << "输入顶点的数目: " << endl;
    cin >> graph->n;
    cout << "输入图中边的数目: " << endl;
    cin >> graph->e;
  
    int u = -1, v = -1;
    for(int i = 0; i < graph->n; i++) {
        graph->adjlist[i].firstarc = NULL;
    }
  
    ArcNode *node;
    for(int i = 0; i < graph->e; i++) {
        cout<<"请输入联通点A与B"<<endl;
        cin >> u >> v ;
        node = (ArcNode *)malloc(sizeof(ArcNode));
        node->adjvex = v;
        node->nextarc = NULL;
        graph->adjlist[u].data = u;
        if(graph->adjlist[u].firstarc == NULL) {
            //边
            graph->adjlist[u].firstarc = node;
        } else {
            //插入边
            insertNode(graph->adjlist[u].firstarc, node);
        }
    }
}
  
void  travseTree() {
    for(int i = 0; i < graph->n; i++) {
        if(graph->adjlist[i].firstarc != NULL) {
            cout <<"与"<< i << "连接的点有:";
            ArcNode *p = graph->adjlist[i].firstarc;
            while(p != NULL) {
                cout << p->adjvex <<  " ";
                p = p->nextarc;
            }
            cout << endl;
        }
    }
}
  
int main(void) {
    create();
    travseTree();
    return 0;
}

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

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

相关文章

2024年有哪些开放式耳机值得入手?开放式耳机排行榜10强

随着技术的不断进步与消费者需求的日益多样化&#xff0c;开放式耳机凭借其独特的优势——如保持对周围环境的感知、减少对耳道的压力等&#xff0c;逐渐成为市场上的一大热点。尤其是在健康意识不断提升的今天&#xff0c;开放式耳机不仅为音乐爱好者提供了全新的聆听体验&…

【C++语言】全面掌握const的用法

一、const 需要怎么理解&#xff1f;&#xff1f; const修饰的变量不能够再作为左值&#xff0c;初始化完成之后&#xff0c;值不能被修改 1.1 C语言的const const 修饰的量&#xff0c;可以不用初始化&#xff0c;不叫常量&#xff0c;叫做常变量。 void main() {const int…

Windows git 配置

需要在git-bash的目录下,配置.ssh 的配置文件 要 .ssh 目录下的配置无法使用

Modbus TCP报错:Response length is only 0 bytes

问题描述&#xff1a; 使用modbus_tk库&#xff0c;通过Modbus tcp连接PLC时&#xff0c;python中的一个报错信息&#xff1a; Response length is only 0 bytes报错原因&#xff1a; 与Modbus TCP 服务端建立连接后没有断开&#xff0c;继续作为长连接使用&#xff0c;客户端…

一文掌握Cephadm部署Ceph存储集群

&#x1f4da; 博客主页&#xff1a; StevenZeng学堂 &#x1f389; 本文专栏: 一文读懂Kubernetes一文读懂Harbor云原生安全实战指南云原生存储实践指南 ❤️ 摘要&#xff1a;随着企业数据量的增长和存储需求的复杂化&#xff0c;Ceph因其高可扩展性和灵活性&#xff0c;能…

AI劳动力崛起:人将面临失业危机?

场景 第一眼看到这个网站的时候&#xff0c;AI员工官网&#xff08;好像是部署在美国&#xff09;&#xff0c;我觉得很好奇&#xff0c;真的可以让AI替代人类完成工作吗&#xff1f;替代到什么程度呢&#xff1f;能以自然语言直接驱动吗&#xff1f; 正好手上在做爬虫项目&am…

HCIP-HarmonyOS Application Developer 习题(十六)

&#xff08;判断&#xff09;1、HiLink通过分布式软总线的方式连接所有设备&#xff0c;强能力设备可对弱能力设备进行设备虚拟化&#xff0c;将弱设备当做本机设备直接调用。 答案&#xff1a;错误 分析&#xff1a;HiLink 主要针对的是应用开发者与第三方设备开发者&#xf…

医院排队叫号系统

医院分诊排队叫号系统是一种广泛应用于服务行业的智能化管理系统&#xff0c;系统可有效地解决病人就诊时排队的无序、医生工作量的不平衡、就诊环境嘈杂等问题&#xff0c;它主要用于改善服务流程&#xff0c;提高服务效率&#xff0c;优化客户体验。这种系统通常包括以下几个…

HarmonyOS Next应用开发——多种方式实现图片解码

【高心星出品】 图片解码 图片处理就是将设备中保存的图片进行编辑处理然后再存储下来&#xff0c;整个过程需要先图片解码&#xff0c;图片处理&#xff0c;最后在图片编码保存。 图片解码指将所支持格式的存档图片解码成统一的PixelMap&#xff0c;以便在应用或系统中进行…

【贝加莱PLC基础教学】2.1 搜索并连接到对应的PLC(1)

【贝加莱PLC基础教学】目录大全_贝加莱plc p23 1361-CSDN博客 PLC其实和单片机差别不大&#xff0c;无非就是大一点的单片机。另外多加了一点点计算机网络和通讯知识&#xff0c;然而就是这一点点计算机网络知识让大家望而却步。 0.基础知识 在计算机网络中&#xff0c;我们通…

Notepad++通过自定义语言实现日志按照不同级别高亮

借助Notepad的自定义语言可以实现日志的按照不同级别的高亮&#xff1b; 参考&#xff1a; https://blog.csdn.net/commshare/article/details/131208656 在此基础上做了一点修改效果如下&#xff1a; xml文件&#xff1a; <NotepadPlus><UserLang name"Ansibl…

深度学习--CNN实现猫狗识别二分类(附带下载链接, 长期有效)

1. 代码实现(包含流程解释) 样本量: 8005 # # 1.导入数据集(加载图片)数据预处理# 进行图像增强, 通过对图像的旋转 ,缩放,剪切变换, 翻转, 平移等一系列操作来生成新样本, 进而增加样本容量, # 同时对图片数值进行归一化[0:1] from tensorflow.keras.preprocessing.image …

Altair官方教程——HyperMesh视觉控制

在HyperMesh中&#xff0c;模型视角控制可通过标准视图&#xff08;Standard Views&#xff09;工具栏、三维视图控制&#xff08;3D View Controls&#xff09;工具栏以及鼠标实现。 (1) 标准视图工具栏图标。 (2) 鼠标控制- 显示控制的推荐操作方法是使用鼠标。配合键盘上的 …

Lfsr32

首先分析 Lfsr5 首先要理解什么是抽头点&#xff08;tap&#xff09;&#xff0c;注意到图中有两个触发器的输入为前级输出与q[0]的异或&#xff0c;这些位置被称为 tap position.通过观察上图&#xff0c;所谓抽头点指的就是第5个&#xff0c;第3个寄存器的输入经过了异或逻辑…

nosql课本习题

nosql题目 1. 文档数据库相比其他 NoSQL 的突出优势和特点是什么&#xff1f; 答案&#xff1a; 文档数据库的突出优势在于它的灵活性和可扩展性。不同于传统的关系型数据库&#xff0c;文档数据库允许存储半结构化和非结构化数据&#xff0c;每个文档可以有不同的字段&#x…

Django操作数据库

Django操作数据库 1、ORM框架2、ORM-创建数据库3、ORM-连接数据库4、ORM-操作表4.1、类创建表4.2、修改表结构4.2.1、删除表结构4.2.2、新增表结构 5、ORM-增删改查5.1、新增数据5.2、删除数据5.3、查询数据5.4、更新数据 1、ORM框架 Django开发操作数据库很简单&#xff0c;内…

沈阳乐晟睿浩科技有限公司技术创新,奠定坚实基础

在当今数字经济蓬勃发展的时代&#xff0c;电子商务以其独特的魅力和无限潜力&#xff0c;正深刻改变着人们的消费习惯与商业模式。在这场变革中&#xff0c;沈阳乐晟睿浩科技有限公司凭借其敏锐的市场洞察力、强大的技术实力以及前瞻性的战略眼光&#xff0c;迅速崛起&#xf…

Java爬虫:获取数据的入门详解

在数字化时代&#xff0c;数据已成为最宝贵的资产之一。无论是市场研究、客户洞察还是产品开发&#xff0c;获取大量数据并从中提取有价值的信息变得至关重要。Java&#xff0c;作为一种成熟且功能强大的编程语言&#xff0c;为编写爬虫提供了强大的支持。Java爬虫可以帮助我们…

月入30万!用AI做养生赚麻了,全网最全最详细的变现教程

现在不养生&#xff0c;将来养医生&#xff01; 秋冬将至&#xff0c;又到了宝子们养生意识季节性觉醒的时间了&#xff0c;这时候&#xff0c;网上关于养生的内容搜索量激增&#xff0c;也催生了AI养生自媒体创作的热潮。 比如这位博主采用养生文案搭配AI简笔画的形式&#…

拥抱新质生产力 | 大势智慧亮相第12届中国测绘地理信息技术装备博览会

10月15日—17日&#xff0c;由中国测绘学会主办的2024中国测绘地理信息科学技术年会暨中国测绘地理信息技术装备博览会在河南省郑州市隆重举行。 10月15日&#xff0c;第12届中国测绘地理信息技术装备博览会在郑州国际会展中心盛大开幕。 大势智慧CTO张帆受邀出席博览会开幕式…