图的初识·存储结构

news2024/11/25 10:38:10

邻接矩阵存储结构

  • 用矩阵表示表示图中各个顶点之间的邻接关系和权值。如图 G = ( V , E ) G=(V,E) G=(V,E),其中有N个结点,使用 N x N NxN NxN的矩阵表示。
    在这里插入图片描述
  • 不带权值的图

G i j = { 1 , 无 向 图 ( v i , v j ) 或 有 向 图 的 < v i , v j > 是 图 中 的 边 0 , 无 向 图 的 ( v i , v j ) 或 有 向 图 的 < v i , v j > 不 是 图 中 的 边 G_{ij}=\begin{cases} 1,无向图(v_i,v_j)或有向图的<v_i,v_j>是图中的边\\ 0,无向图的(v_i,v_j)或有向图的<v_i,v_j>不是图中的边 \end{cases} Gij={1,(vi,vj)<vi,vj>0,(vi,vj)<vi,vj>

  • 举例
    在这里插入图片描述
  • 由于无向图没有方向之分,顶点之间是相互连接的,所以无向图的邻接矩阵必定是一个对称矩阵。
  • 无向图的邻接矩阵是一个对称矩阵,存储时为节约时间,我们只存放上半部分。
  • 带权值的图
    G i j = { w i j , 无 向 图 的 ( v i , v j ) 或 有 向 图 < v i , v j > 是 图 中 的 边 0 或 ∞ , 无 向 图 的 ( v i , v j ) 或 有 向 图 的 < v i , v j > 不 是 图 中 的 边 G_{ij}=\begin{cases} w_{ij},无向图的(v_i,v_j)或有向图<v_i,v_j>是图中的边\\ 0或\infty,无向图的(v_i,v_j)或有向图的<v_i,v_j>不是图中的边 \end{cases} Gij={wij,(vi,vj)<vi,vj>0,(vi,vj)<vi,vj>
    在这里插入图片描述

总结

  • 对于无向图,邻接矩阵的第 i i i行非 0 0 0(或非 ∞ \infty )的个数就是第 i i i个顶点的度
  • 对于有向图,邻接矩阵的第 i i i行非 0 0 0(或非 ∞ \infty )的个数就是第 i i i个顶点的出度(横向表示出度,纵向表示入度)

代码实现·有向图

#include<stdio.h>
#include<stdlib.h>
typedef char E;//定点存放的数据类型
#define MaxVertex 5
typedef struct MatrixGraph {
    int vertexCount;//顶点数
    int edgeCount;//边数
    int matrix[MaxVertex][MaxVertex];//矩阵的长,宽
    E data[MaxVertex];//各个顶点对应的数据
}* Graph;

//创建矩阵
Graph Create();
//添加各个顶点的数据
void addVertex(Graph graph,E element);
//存储边的关系
void addEdge(Graph graph,int i,int j);
#include "Map.h"
//创建矩阵
Graph Create() {
    //将结构体创建出来,注意使用动态内存,否则函数结束,栈空间会被回收
    //结构体中的数组也会创建出来
    Graph graph= (Graph)malloc(sizeof(struct MatrixGraph));
    graph->vertexCount=0;
    graph->edgeCount=0;
    //因为内存中的数据随机值,所以将其初始化为0,方便后续的使用
    for(int i=0;i<MaxVertex;i++) {
        for(int j=0;j<MaxVertex;j++) {
            graph->matrix[i][j]=0;
        }
    }
    return graph;
}

//添加各个顶点的数据
void addVertex(Graph graph,E element) {
    //当结点数量大于等于节点数时,结束函数
    if(graph->vertexCount>=MaxVertex) return;
    //采用后置加加的方式,将元素存储进去
    graph->data[graph->vertexCount++]=element;
}

//存储边的关系
void addEdge(Graph graph,int i,int j) {
    //初始化时已经将全部的数据置为0
    if(graph->matrix[i][j]==0) {
        //注意如果时无向图的话,就将[i][j]和[j][i]都置为1
        graph->matrix[i][j]=1;
        graph->edgeCount++;//边的条数+1
    }
}
//打印邻接矩阵
void printGraph(Graph graph) {
    for(int i=-1;i<graph->vertexCount;i++) {
        for(int j=-1;j<graph->vertexCount;j++) {
            if(j==-1) {//打印第一行的字母
                printf("%c",'A'+i);
            }else if(i==-1) {//打印从第二行起的首字母
                printf("%3c",'A'+j);
            }else {//打印矩阵的内容
                printf("%3d",graph->matrix[i][j]);
            }
        }
        putchar('\n');
    }
}
#include "Map.h"
int main() {
    Graph graph=Create();
    for(int c='A';c<='D';c++)
        addVertex(graph,(char)c);
    addEdge(graph,0,1);//A->B
    addEdge(graph,1,2);//B->C
    addEdge(graph,2,3);//C->D
    addEdge(graph,3,0);//D->A
    addEdge(graph,2,0);//C->A
    printGraph(graph);
    return 0;
}

在这里插入图片描述

邻接表

  • 对于图中的每个顶点。建立一个数组,存放一个头结点,与其邻接的顶点相连。
  • 有向图
    在这里插入图片描述
  • 无向图
    在这里插入图片描述

代码实现·有向图

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#define MaxVertex 5
typedef char E;
//结点和头节点分开定义,普通结点记录邻接顶点信息
typedef struct node {
    int nextVertex;
    struct node *next;
} *Node;
//头节点记录元素
struct HeadNode {
    E element;
    struct node * next;
};

typedef struct AdjacencyGraph {
    int vertexCount;//顶点数
    int edgeCount;//边数
    struct HeadNode vertex[MaxVertex];
}* Graph;
//初始化
Graph create();
//添加顶点
void addVertex(Graph graph,E element);
//添加边的关系
void addEdge(Graph graph,int a,int b);
//打印邻接表
void printGraph(Graph graph);
#include "Map2.h"
//创建
Graph create() {
    Graph graph=(Graph) malloc(sizeof(struct AdjacencyGraph));
    graph->vertexCount=graph->edgeCount=0;
    return graph;
};
//添加顶点
void addVertex(Graph graph,E element) {
    if(graph->vertexCount>=MaxVertex) return;
    //添加新节点
    graph->vertex[graph->vertexCount].element=element;
    graph->vertex[graph->vertexCount].next=NULL;
    graph->vertexCount++;//顶点数更新
}
void addEdge(Graph graph,int a,int b) {
    //定义一个指向链表的头结点的下一结点指向
    Node node=graph->vertex[a].next;
    //开辟顶点空间
    Node newNode=(Node) malloc(sizeof(struct node));
    newNode->next=NULL;
    newNode->nextVertex=b;
    //如果头结点下面没有东西,就直接连接;否则,就遍历到最后一个结点后,添加新节点
    if(!node) {
        graph->vertex[a].next=newNode;//注意这里不能使用node,因为我们要真实地改变头节点的next指向
    }else {
        do{
            //如果已经连接到对应的结点,直接返回
            if(node->nextVertex==b) {
                free(newNode);
                newNode=NULL;
                return ;
            }
            //否则一直遍历到最后一个结点
            if(node->next) node=node->next;
            else break;//如果遭到了最后一个结点,直接结束
        }while(true);
        node->next=newNode;
    }
    graph->edgeCount++;//边数计数+1
}
//打印
void printGraph(Graph graph) {
    for(int i=0;i<graph->vertexCount;i++) {
        printf("%d | %c",i,graph->vertex[i].element);
        Node node=graph->vertex[i].next;
        while(node) {
            printf("-> %d",node->nextVertex);
            node=node->next;
        }
        printf("\n");
    }
}
#include "Map2.h"
int main() {
    Graph graph=create();
    for(int c='A';c<='D';c++) {
        addVertex(graph,(char)c);
    }
    addEdge(graph,0,1);//A->B
    addEdge(graph,1,2);//B->C
    addEdge(graph,2,3);//C->D
    addEdge(graph,3,0);//D->A
    addEdge(graph,2,0);//C->A
    printGraph(graph);
}

在这里插入图片描述

  • 缺点:无法快速计算顶点的入度数。
  • 解决方法:再用一组邻接表,专门记录入度的关系。
    在这里插入图片描述

总结

  • 邻接矩阵:适合稠密图
  • 邻接表:适合稀疏图

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

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

相关文章

猕猴桃的红色果肉受到特定的激活-抑制系统的控制

文章信息 题目&#xff1a;The red flesh of kiwifruit is differentially controlled by specific activation–repression systems 刊名&#xff1a;New Phytologist 作者&#xff1a;Wen-qiu Wang&#xff0c;Andrew C. Allan,Xue-ren Yin et al 单位&#xff1a;Zhejia…

猿如意开发工具|Sublime Text(4126)

文章目录 一、猿如意是什么&#xff1f; 二、如何使用猿如意下载安装Sublime Text 三、总结 一、猿如意是什么&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段搜索&#xff0c;全网搜…

【Pandas数据处理100例】(九十九):Pandas使用at_time()筛选出特定时间点的数据行

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

如何建立一套完善的销售管理体系?

怎样创建两套健全的产品销售体系&#xff1f;用工程建设观念管理工作产品销售项目组&#xff0c;创建健全的产品销售体系&#xff01; 逐步形成精确的最终目标虽说重要&#xff0c;但缺乏有效率的方式来破冰&#xff0c;最终目标可能将仅是这份无用。 篮球赛事球手的最终目标…

IOC 的底层原理和Bean管理XML方式、xml注入集合属性

目录 什么是IOC IOC底层管理 工厂模式 IOC 的过程 IOC 接口 IOC 操作Bean 原理 Bean 管理操作有两种方式 1. 基于xml 配置方式创建对象 2. 基于xml方式注入属性 第二种使用有参数构造注入 p 名称空间注入 ICO操作Bean管理&#xff08;xml 注入其他类型属性&#xff…

微信小程序的 websocket 以及 微信开发者工具测试 ws 协议没有数据的 离奇解决方案 记录

微信小程序的 websocket 在本地web能够使用ws协议去链接websocket&#xff0c;但是小程序不能使用。一、WSS 协议与 WS 协议二、业务场景记录 : 使用 ws 协议的 websocekt 做测试,但是在 h5中可以拿到实时数据,在微信开发者工具中以及真机调试中拿不到模拟数据的问题1. 首先在 …

2022安洵杯babybf

babybf 赛后分析了下&#xff0c;发现是一道很有意思的题目 Brainfuck是一种极小化的计算机语言&#xff0c;它是由Urban Mller在1993年创建的。由于fuck在英语中是脏话&#xff0c;这种语言有时被称为brainf*ck或brainf**k&#xff0c;甚至被简称为BF。 其实本题是一个c语言实…

三、【redux】异步action

文章目录1、不成熟的异步修改1.1、CODE1.1.1、count_action.js1.1.1、count_reducer.js1.2、异常2、异步action代码修正2.1、store.js2.2、count_action.js3、小总结action分两类&#xff1a; 同步&#xff1a;指action的值是Object类型的一般对象异步&#xff1a;指action的值…

在C#中使用Halcon开发视觉检测程序

本文的初衷是希望帮助那些有其它平台视觉算法开发经验的人能快速转入Halcon平台下&#xff0c;通过文中的示例开发者能快速了解一个Halcon项目开发的基本步骤&#xff0c;让开发者能把精力完全集中到算法的开发上面。 首先&#xff0c;你需要安装Halcon&#xff0c;HALCON 18.…

D. X-Magic Pair(辗转相除)

Problem - 1612D - Codeforces 给你一对整数&#xff08;a,b&#xff09;和一个整数x。 你可以用两种不同的方式改变这对整数。 设置&#xff08;分配&#xff09;a:|a-b|。 设置&#xff08;分配&#xff09;b:|a-b|。 其中|a-b|是a和b之间的绝对差值。 如果只用给定的操作就…

【Linux】shell命令行简单解释器

回顾一下&#xff0c;我们前面学习了进程创建&#xff0c;进程终止&#xff0c;进程等待&#xff0c;进程替换&#xff0c;通过这些内容我们可以来进行实现简单的shell命令行解释器&#xff01;&#xff01;&#xff01;下面我们直接来看一看如何去实现shell命令行解释器&#…

结合编辑器和PDFXplorer工具查看PDF文件结构

首先用编辑器打开PDF,可以看到如下结构 1.寻找文件结构入口 /Root k-value形式&#xff0c;/Root 98 0 R/ k是Root value是98 0 R 98 0 R 代表被引用&#xff0c;指向的对象是98 0 obj 用PDFExploer工具打开看&#xff0c;如下&#xff1a; 可以看出用工具打开的树形结构跟上…

[附源码]计算机毕业设计springboot快转二手品牌包在线交易系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

YonBuilder开发之后端函数

在前几期的文章中我们已经介绍过如何在YonBuilder中使用前端函数实现数据过滤功能。相对应于前端函数&#xff0c;在YonBuilder中还可以使用后端函数实现对于程序的扩展。通过前端函数实现的更多的是与页面交互相关的功能&#xff0c;而后端函数主要是用于预制按钮功能的扩展开…

Mybatis的介绍及使用

目录 Mybatis 搭建MyBatis开发环境 1、创建Maven工程&#xff0c;导入MyBatis依赖的组件 2、编写MyBatis核心配置文件(mybatis-config.xml) 3、创建实体类-POJO 4、创建SQL映射文件(mapper.xml) 5、创建测试类 Mybatis MyBatis是一款优秀的持久层框架&#xff0c;用于简…

时光邮局|来写一封未来的信试试吧!一个我的新项目,Java+Vue

什么是时光邮局&#xff1f; 漫漫星河璀璨&#xff0c;漫漫古道长河。 官网&#xff1a;云寄-时光邮局 寻找一份特殊的意义&#xff0c;学会热爱生活&#xff0c;学会面朝大海。 有一天我收到了两年前的自己来信。 如果可以给末来寄信你会写些什么呢&#xff1f; 如果能收到两…

分析网上的一篇“浪漫烟花“程序<VS-C++>

结果:多个烟花弹同时上升,然后进行爆炸,并进行了花样设计,采取心型设计方案,背景音乐设置为"小幸运",除此在最初,窗口设置有文本. 接下来,就让我们来分析代码: // 烟花结构 struct FIRE {int r; // 当前爆炸半径int max_r; // 爆炸中心距离边缘最大半径int …

简述RabbitMQ的架构设计

Broker&#xff1a; rabbitmq的服务节点Queue&#xff1a; 队列&#xff0c;是RabbitMQ的内部对象&#xff0c;⽤于存储消息。RabbitMQ中消息只能存储在队列中。⽣产者投递消息到队列&#xff0c;消费者从队列中获取消息并消费。多个消费者可以订阅同⼀个队列&#xff0c;这时队…

Windows系统--AD域控--DHCP服务器

Windows系统--AD域控--DHCP服务器 虚拟机网络准备 1.将VMware网络编辑器的NAT模式--取消勾选 使用本地DHCP服务器; 从机(win10)将内置网卡的IPv4网络改为 自动获取IP地址、自动获取DNS AD服务器 部署 DHCP服务器

springboot+java+vue.js教室自习室座位预订系统

目 录 摘 要 I Abstract II 第1章 前 言 2 1.1 研究背景 3 1.2 研究现状 3 1.3 系统开发目标 3 第2章 系统开发环境 5 2.1 java技术 5 2.2 Mysql数据库 6 2.3 B/S结构 7 2.4 springboot框架 7 2.5 ECLIPSE 开发环境 7 第3章 需…