图的初识·存储结构
创始人
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);
}

在这里插入图片描述

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

总结

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

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...