系列文章目录

第九话  数据结构之图的存储

文章目录

  • 一、了解什么是图
  • 二、图的定义和基本术语
  • 三、存储结构之邻接矩阵
    • 1.邻接矩阵的介绍
    • 2.邻接矩阵的创建
    • 3.主函数中实现
  • 四、存储结构之邻接表
    • 1.邻接表的介绍
    • 2.邻接表的创建
    • 3.在主函数中实现
  • 五、总结

前言

一切尽在图结构

图的应用非常广泛,可以用图来表示物体的外形、城市的布局、经济的增长、程序的流程,甚至心情的好坏。

自然界的很多现象都可以抽象成一个图结构,计算机网络可以抽线成一张网络图,设计程序时就会画一张流程图,航空公司的航班路线也是一张图,旅游公司的行程也是一张流程图,有机化学分子也可用图来表示,图无处不在。

一、了解什么是图

图是一种比线性表和树更为复杂的数据结构,在图结构中,节点之间的关系可以是任意的,任意两个元素之间都可能相关,所以图结构被用于描述各种复杂的数据对象。

图是一种数据结构。图的基本操作主要有创建、插入、删除、查找等。从图的逻辑结构定义可知,无法将图中的顶点排列成一个唯一的线性序列。

可将任意一个顶点看成是图的一个顶点,同理,对于任意一个顶点而言,其邻接点之间也不存在顺序关系。但为了便于对图进行操作,需要将图中的顶点按任意序列排列起来

二、图的定义和基本术语

1、有向图和无向图

图的定义:用顶点集合和边集合组合起来的集合称为图

对于图而言,分为有向图和无向图

有向图如下: 

无向图如下:

有向图的介绍::

 有向图:在有向图中,顶点对用一对尖括号括起来,即<x,y>,这个是有序的,x是有向边的起始点,y是有向边的终点。<x.y>总体表示从顶点x到顶点y的一条有向边,<x,y>带表一条边,因为是有向的,所以<x,y>和<y,x>是两条不同的边。

无向图的介绍: 

无向图:在无向图中,顶点对用一对圆括号括起来,即(x,y),这个是无序的,由于是无向的。所以这条边没有特定的方向,(x,y)和(y,x)是同一条边。

2、图的基本术语

无向完全图:对于无向图,如果任意两顶点都有一条边直接连接,则称该图为无向完全图。顶点n与边a的关系为:a = n(n-1)/2

有向完全图:对于有向图,如果任意两顶点之间都有方向互为相反的两条弧相连接,则称该图为有向完全图。顶点n与弧a的关系为:a = n(n-1)

三、存储结构之邻接矩阵

1、邻接矩阵

邻接矩阵是表示顶点之间相邻关系的矩阵,用一维数组存储图中顶点的信息,用矩阵表示图中各顶点之间的邻接关系。

在无向图中,若两顶点之间是连通的,则用1表示,否则用0表示。

在有向图中,若A能够到B,则A到B表示1,没有方向连接的用0表示。

2、无向图的邻接矩阵存储

首先我们把ABCD分别编序为0,1,2,3

1.邻接矩阵存储

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
//无向图的邻接矩阵
typedef struct
{char data[MAXSIZE];//顶点数组int arc[MAXSIZE][MAXSIZE];//邻接矩阵int vexnum, edgenum;//当前的定点数和边数}MGraph;

2.邻接矩阵的创建

//图的邻接矩阵的创建
void CreateMgrapg(MGraph *p)
{int i, j, k;printf("输入定点数和弧数:");scanf("%d %d", &p->vexnum,&p->edgenum);//输入顶点数和弧数printf("输入所有顶点的信息:");for (i=0; i<p->vexnum;i++){scanf(" %c",&p->data[i]);}for (i = 0;i < p->vexnum;i++){for (j = 0;j<p->vexnum;j++){p->arc[i][j] = 0;}}for (k=0; k < p->edgenum; k++){printf("输入第%d弧的两个顶点的序号,格式(i j):",k+1);scanf("%d %d", &i, &j);p->arc[i][j] = 1;p->arc[j][i] = 1;//去掉这个代表有向图}
}

3.邻接矩阵的输出及在主函数中实现 

void print(MGraph g)
{int i,j;for (i = 0; i < g.vexnum; i++){for (j = 0; j < g.vexnum; j++){printf("%-3d", g.arc[i][j]);}printf("\n");}
}
int main()
{MGraph g;CreateMgrapg(&g);print(g);return 0;
}

4.实现如下

5.完整代码如下 

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
//无向图的邻接矩阵
typedef struct
{char data[MAXSIZE];//顶点数组int arc[MAXSIZE][MAXSIZE];//邻接矩阵int vexnum, edgenum;//当前的定点数和边数}MGraph;
//图的邻接矩阵的创建
void CreateMgrapg(MGraph *p)
{int i, j, k;printf("输入定点数和边数:");scanf("%d %d", &p->vexnum,&p->edgenum);//输入顶点数和边数printf("输入所有顶点的信息:");for (i=0; i<p->vexnum;i++){scanf(" %c",&p->data[i]);}for (i = 0;i < p->vexnum;i++){for (j = 0;j<p->vexnum;j++){p->arc[i][j] = 0;}}for (k=0; k < p->edgenum; k++){printf("输入第%d边的两个顶点的序号,格式(i j):",k+1);scanf("%d %d", &i, &j);p->arc[i][j] = 1;p->arc[j][i] = 1;//去掉这个可以表示有向图}
}
void print(MGraph g)
{int i,j;for (i = 0; i < g.vexnum; i++){for (j = 0; j < g.vexnum; j++){printf("%-3d", g.arc[i][j]);}printf("\n");}
}
int main()
{MGraph g;CreateMgrapg(&g);print(g);return 0;
}

四、存储结构之邻接表

1、邻接表

邻接表是图的一种链式存储结构。在邻接表中,对图中每个顶点建立一个单链表,把相邻的顶点放在这个链表中。

​​​​​​​

2、有向图的邻接表存储 

首先我们把ABCD分别编序为0,1,2,3

1.邻接表存储

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
//有向图邻接表的存储
typedef char VertexType;
typedef struct node{//定义边表结点int adjvex;//邻接点域struct node *next;//指向下一个邻接点域的指针域
}EdgeNode;
typedef struct vexnode{//定义顶点表结点VertexType data;//顶点域EdgeNode *firstedge;//指向第一条边结点
}VHeadeNode;
typedef struct{VHeadeNode adjlist[MAXSIZE];/*邻接表头结点数组*/int n,e;//顶点数,边数
}AdjList;

2.邻接表的创建 

void GreateAGraph(AdjList *g){int i,j,k;printf("请输入图的顶点数和边数:");scanf("%d %d",&g->n,&g->e);printf("请输入图的所有顶点信息:");for(i=0;i<g->n;i++){scanf(" %c",&(g->adjlist[i].data));//给图的每个结点的顶点域赋值g->adjlist[i].firstedge = NULL;//首先点的边表头指针都设为空}EdgeNode *p;for(k=0;k<g->e;k++){printf("请输入第%d条边对应的两个顶点的序号,格式(i j):",k+1);scanf("%d %d",&i,&j);p = (EdgeNode*)malloc(sizeof(EdgeNode));p->adjvex = j;p->next = g->adjlist[i].firstedge;//头插法g->adjlist[i].firstedge = p;}
}

3.邻接表的输出及在主函数中实现 

/邻接表的输出
void printadj(AdjList *g){int i;EdgeNode *p;for(i=0;i<g->n;i++){printf("%2d [%c]",i,g->adjlist[i].data);p = g->adjlist[i].firstedge;while(p!=NULL){printf("-->[%d]",p->adjvex);p = p->next;}printf("\n");}
}
int main() {AdjList G;GreateAGraph(&G);//创建有向图printadj(&G);return 0;
}

4.实现如下 

5.完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
//有向图邻接表的存储
typedef char VertexType;
typedef struct node{//定义边表结点int adjvex;//邻接点域struct node *next;//指向下一个邻接点域的指针域
}EdgeNode;
typedef struct vexnode{//定义顶点表结点VertexType data;//顶点域EdgeNode *firstedge;//指向第一条边结点
}VHeadeNode;
typedef struct{VHeadeNode adjlist[MAXSIZE];/*邻接表头结点数组*/int n,e;//顶点数,边数
}AdjList;//有向图邻接表的创建
void GreateAGraph(AdjList *g){int i,j,k;printf("请输入图的顶点数和边数:");scanf("%d %d",&g->n,&g->e);printf("请输入图的所有顶点信息:");for(i=0;i<g->n;i++){scanf(" %c",&(g->adjlist[i].data));//给图的每个结点的顶点域赋值g->adjlist[i].firstedge = NULL;//首先点的边表头指针都设为空}EdgeNode *p;for(k=0;k<g->e;k++){printf("请输入第%d条边对应的两个顶点的序号,格式(i j):",k+1);scanf("%d %d",&i,&j);p = (EdgeNode*)malloc(sizeof(EdgeNode));p->adjvex = j;p->next = g->adjlist[i].firstedge;//头插法g->adjlist[i].firstedge = p;}
}
//邻接表的输出
void printadj(AdjList *g){int i;EdgeNode *p;for(i=0;i<g->n;i++){printf("%2d [%c]",i,g->adjlist[i].data);p = g->adjlist[i].firstedge;while(p!=NULL){printf("-->[%d]",p->adjvex);p = p->next;}printf("\n");}
}
int main() {AdjList G;GreateAGraph(&G);//创建有向图printadj(&G);return 0;
}

五、总结

邻接矩阵:

优点:很容易确定任意两个顶点之间是否有边相邻

缺点:不便添加和删除顶点、不便统计边的数目

邻接表

优点:方便增加和删除顶点、易于统计边的数目、空间效率高

缺点:不便判断顶点间是否有边、不便计算有向图中各个顶点的度

总体注意:一个图的邻接矩阵表示是唯一的,但其邻接表表示不是唯一的。因为邻接表表示中,链接次序取决于算法、边和输入顺序

数据结构--图的存储结构相关推荐

  1. 20.0、C语言数据结构——图的存储结构

    20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...

  2. 数据结构——图(存储结构)

    数据结构--图 图的定义和基本术语 图的类型定义 图的存储结构 数组(邻接矩阵表示法) 网(即有权图)的邻接矩阵表示法 邻接表 邻接表表示法(链式) 图的邻接表存储表示 采用邻接表表示法创建无向网 邻 ...

  3. 数据结构——图的存储结构

    邻接矩阵法 通过矩阵来表示所有的 有向图的邻接矩阵法 无向图的邻接矩阵法 无向图的矩阵一定是对称的,可以才用压缩存储方式 网的邻接矩阵法 网就是带权值的图,所以数组里面直接放权值,不存在的边用正无穷表 ...

  4. 数据结构——图:极大小连通子图、图的存储结构、图的遍历

    图的基本概念: 极大连通子图就是连通分量. 极大连通子图与连通分量在无向图(undirected graph)这个前提下是等同的概念. 极小连通子图: 减去任何一条边就不再连通. 不管树还是二叉树:n ...

  5. 【数据结构——图和图的存储结构】

    目录 一.图的定义和基本术语(Graph) (一)图的定义 (二)图的基本术语 一.图的存储结构 (一)邻接矩阵(Adjacency Matrix) 1.无向图的邻接矩阵 2.有向图的邻接矩阵 3.网 ...

  6. 数据结构之图的存储结构:邻接多重表

    图的存储结构:邻接多重表 产生条件: 邻接多重表的定义: 邻接多重表的代码定义: 删除: 性能分析: 十字链表与邻接多重表的对比 产生条件: 当用邻接矩阵法存储时:空间复杂度为O(|V|^2),太大 ...

  7. 数据结构之图的存储结构:十字链表法

    图的存储结构:十字链表法 思维导图: 产生条件: 十字链表法的定义: 十字链表法的代码定义: 性能分析: 思维导图: 产生条件: 当用邻接矩阵存储时:空间复杂度为O(|v|^2),太大 当用邻接表法存 ...

  8. 数据结构之图的存储结构:邻接表法

    图的存储结构:邻接表法 产生条件: 邻接表法的定义: 邻接表法的特点: 邻接表法的代码定义: 邻接表法与邻接矩阵法的对比: 产生条件: 当用邻接矩阵存储时:空间复杂度为O(|v|^2),太大 邻接表法 ...

  9. 数据结构之图的存储结构:邻接矩阵法

    图的存储结构:邻接矩阵法 邻接矩阵法: 邻接矩阵的定义: 邻接矩阵存储无向图: 邻接矩阵存储有向图: 邻接矩阵存储网: 邻接矩阵法的性质: 邻接矩阵法的代码实现: 矩阵运算A的n次幂的含义: 性能分析 ...

最新文章

  1. pandas使用read_csv函数读取文件时指定数据列的数据类型、pandas使用read_csv函数读取文件时通过keep_default_na参数设置缺失值替换为空字符串
  2. JavaScript运算符:递增递减运算符前置和后置的区别
  3. 蹭课神器NABCD分析
  4. equals方法重写详解
  5. nginx.conf 配置文件详解
  6. 被坑;剪头发(普通修剪)180元!你会怎么办?
  7. 【Proteus仿真8086实验一】RAM存储器62256
  8. Could not resolve type alias ‘‘
  9. ubuntu apt-get 安装软件时自动yes
  10. 大数据技术原理与应用学习笔记(一)
  11. EDA第一次课<1117电路图的绘制>
  12. js中继承的几种方式
  13. android九游sdk,九游单机SDK接入常见问题
  14. Photoshop 换脸大法
  15. java 小程序 学生成绩_自己搞的小程序,学生管理信息系统,大家来看看
  16. 网站分析-网站流量分析
  17. 关于Eclipse4.7安装TomcatPlugin后无法显示三只猫问题
  18. 学微信小程序要学些什么?
  19. moment 常用时间方法
  20. LinearLayout下如何实现两端对齐

热门文章

  1. windows找不到gpedit.msc请确定文件名
  2. 如何手动制作透明的图片相框 可以供android使用
  3. 007需求分析中的重要知识点(马斯洛需求层次理论+KANO优先级筛选模型+金字塔模型)
  4. 校验码 - 奇偶校验
  5. 1.11 Illustrator视图的预览模式 [Illustrator CC教程]
  6. Android studio中如何利用Debug模式来调试程序
  7. average and standard deviation-平均数和标准差
  8. 常见Oracle错误都在这了: ORA-00257/ORA-00313/ORA-28000/ORA-28000
  9. APP运营精华:6种营销推广模式
  10. 【小白】Open-CV 学习笔记 -5.5.2 离散傅里叶变换相关函数详解