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

在这里插入图片描述

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

总结

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

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...