图的初识·存储结构
创始人
2024-03-03 16:52:42
0

邻接矩阵存储结构

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

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

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

总结

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

代码实现·有向图

#include
#include
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;ifor(int j=0;jgraph->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) {//初始化时已经将全部的数据置为0if(graph->matrix[i][j]==0) {//注意如果时无向图的话,就将[i][j]和[j][i]都置为1graph->matrix[i][j]=1;graph->edgeCount++;//边的条数+1}
}
//打印邻接矩阵
void printGraph(Graph graph) {for(int i=-1;ivertexCount;i++) {for(int j=-1;jvertexCount;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->BaddEdge(graph,1,2);//B->CaddEdge(graph,2,3);//C->DaddEdge(graph,3,0);//D->AaddEdge(graph,2,0);//C->AprintGraph(graph);return 0;
}

在这里插入图片描述

邻接表

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

代码实现·有向图

在这里插入图片描述

#include 
#include 
#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;ivertexCount;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->BaddEdge(graph,1,2);//B->CaddEdge(graph,2,3);//C->DaddEdge(graph,3,0);//D->AaddEdge(graph,2,0);//C->AprintGraph(graph);
}

在这里插入图片描述

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

总结

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

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...