图的存储
2020-04-30 本文已影响0人
大橘猪猪侠
定义:图形结构是一种比树形结构更复杂的非线性结构。在树形结构中,结点间具有分支层次关系,每一层上的结点只能和上一层中的至多一个结点相关,但可能和下一层的多个结点相关。而在图形结构中,任意两个结点之间都可能相关,即结点之间的邻接关系可以是任意的 。
图的结构有无向图,有向图,网图
无向图.png 有向图.png 网图.png上面三张图分别是不同的结构图像
而实现图的存储结构有两种:
一、邻接矩阵
二、邻接表
下面通过分别通过两种方式去实现图的结构
一、邻接矩阵:
邻接矩阵使用而为数组来描述图的结构,如果是无向图,邻接矩阵与主对角对称。
截屏2020-04-30 上午11.32.06.pngtypedef int Status; //函数状态值
typedef char VertexType; //顶点类型
typedef int EdgeType; //边上的权值
typedef struct {
VertexType vexs[MAXVEX];//顶点表
EdgeType arc[MAXVEX][MAXVEX];//w q图中当前的顶点数和边数
int numNodes,numEdges;//图中当钱的顶点数和边数
}MGraph;
void CreateMGraph(MGraph *G){
int i,j,k,w;
printf("输入顶点数和边数:\n");
//1、输入顶点数/边数
scanf("%d,%d",&G->numNodes,&G->numEdges);
printf("顶点数:%d,边数:%d\n",G->numNodes,G->numEdges);
//2、输入顶点信息/顶点表
for (i = 0; i<=G->numNodes; i++) {
scanf("%c",&G->vexs[i]);
}
//3、初始化邻接矩阵
for (i = 0; i<G->numNodes; i++) {
for (j = 0; j<G->numNodes; j++) {
G->arc[i][j] = INFINITYC;
}
}
//4、输入边表信息
for (k = 0; k<G->numEdges; k++) {
printf("输入边(vi,vj)上的下标i,下标j,权值w\n");
scanf("%d,%d,%d",&i,&j,&w);
G->arc[i][j] = w;
//如果无向图,矩阵对称(可以自己对是否为有向图或无向图进行设置判断)
G->arc[j][i] = G->arc[i][j];
}
//5、打印邻接矩阵
for (i = 0; i<G->numNodes; i++) {
printf("\n");
for (j = 0; j<G->numNodes; j++) {
printf("%d ",G->arc[i][j]);
}
}
printf("\n");
}
打印输出
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"邻接矩阵实现图的存储!");
MGraph G;
CreateMGraph(&G);
}
return 0;
}
/*
2020-04-30 11:22:01.704420+0800 图的存储[1483:78312] 邻接矩阵实现图的存储!
输入顶点数和边数:
5,6
顶点数:5,边数:6
abcde
输入边(vi,vj)上的下标i,下标j,权值w
0,4,6
输入边(vi,vj)上的下标i,下标j,权值w
1,0,9
输入边(vi,vj)上的下标i,下标j,权值w
1,2,3
输入边(vi,vj)上的下标i,下标j,权值w
2,0,2
输入边(vi,vj)上的下标i,下标j,权值w
2,3,5
输入边(vi,vj)上的下标i,下标j,权值w
3,4,1
0 9 2 0 6
9 0 3 0 0
2 3 0 5 0
0 0 5 0 1
6 0 0 1 0
*/
二、邻接表
[图片上传失败...(image-bee723-1588218029752)]
看上图中的结构,我们可以创建n个链表,(n为节点的数量),然后将所有链表添加进去数组当中,然后对数组中的每一个链表的下一个值插入该节点连接的节点,进行遍历,将他们连接起来
#define M 100
#define FALSE 0
#define TRUE 1
typedef char Element;
typedef int BOOl;
typedef struct Node{
int adj_vex_index;//弧头的下标,也就是被指向的下标
Element data;//权重值
struct Node *next; //边指针
}EdgeNode;
//顶点节点表
typedef struct VNode{
Element data;//顶点的权值
EdgeNode *firstedge;//顶点的下一个是谁
}VertexNode,Adjlist[M];
//总图的一些信息
typedef struct Graph{
Adjlist adjlist;//顶点表
int arc_num;//边的个数
int node_num;//节点个数
BOOl is_directed;//是不是有向图
}Graph,*GraphLink;
void CreateGraph(GraphLink *g){
int i,j,k;
EdgeNode *p;
//1、顶点,边,是否有向
printf("输入顶点数目,边数和有向:\n");
scanf("%d,%d,%d",&(*g)->node_num,&(*g)->arc_num,&(*g)->is_directed);
//2、顶点表
printf("输入顶点信息:\n");
for (i = 0; i<(*g)->node_num; i++) {
getchar();
scanf("%c",&(*g)->adjlist[i].data);
(*g)->adjlist[i].firstedge = NULL;
}
//3、输入边的信息
printf("输入边的信息:\n");
for (k = 0; k<(*g)->arc_num; k++) {
getchar();
scanf("%d,%d",&i,&j);
//1、新建一个节点
p = (EdgeNode *)malloc(sizeof(EdgeNode));
//2、弧头的下标
p->adj_vex_index = j;
//3、头插法插进去,插的时候要找弧尾,那就是顶点数组的下标i
p->next = (*g)->adjlist[i].firstedge;
//4、将顶点数组[i].firstedge设置为p
(*g)->adjlist[i].firstedge = p;
//j->i
if(!(*g)->is_directed){
//1、新建一个节点
p = (EdgeNode *)malloc(sizeof(EdgeNode));
//2、弧头的下标i
p->adj_vex_index = i;
//3、头插法插进去,插的时候找到弧尾,那就是顶点数组的下标i
p->next = (*g)->adjlist[j].firstedge;
//4、将顶点数组[i].firstedge设置为p
(*g)->adjlist[j].firstedge = p;
}
}
}
//打印输出
void putGraph(GraphLink g){
int i;
printf("邻接表中存储信息\n");
//遍历一遍顶点坐标,每个再进去走一次
for (i = 0; i<g->node_num; i++) {
EdgeNode *p = g->adjlist[i].firstedge;
while (p) {
printf("%c->%c ",g->adjlist[i].data,g->adjlist[p->adj_vex_index].data);
p = p->next;
}
printf("\n");
}
}
打印结果
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"邻接表实现图的存储!");
GraphLink g = (Graph *)malloc(sizeof(Graph));
CreateGraph(&g);
putGraph(g);
}
return 0;
}
/*
打印结果
2020-04-30 11:24:44.034591+0800 邻接表[1490:80421] 邻接表实现图的存储!
输入顶点数目,边数和有向:
4,5,0
输入顶点信息:
0 1 2 3
输入边的信息:
0,1
0,2
0,3
2,1
2,3
邻接表中存储信息
0->3 0->2 0->1
1->2 1->0
2->3 2->1 2->0
3->2 3->0
Program ended with exit code: 0
*/