栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

图的存储结构的实现(C语言 邻接表/邻接矩阵)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

图的存储结构的实现(C语言 邻接表/邻接矩阵)

  • 因图中可能存在回路,某些顶点可能会被重复访问,那么如何避免遍历不会因回路而陷入死循环。

解决方案:附设访问标志数组visited[n] 。

代码如下:

void initVisited(int vertexNum)
{
	int i;
	for (i=0; i 
邻接矩阵实现图的存储结构 
  • 是否可以采用顺序存储结构存储图?

图的特点:顶点之间的关系是m:n,即任何两个顶点之间都可能存在关系(边),无法通过存 储位置表示这种任意的逻辑关系,所以,图无法采用顺序存储结构。

  • 如何存储图?

考虑图的定义,图是由顶点和边组成的,分别考虑如何存储顶点、如何存储边。

  • 邻接矩阵数组表示

基本思想:用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。

假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n的方阵,定义为:

arc[i][j]=        1        若(vi, vj)∈E(或∈E)
                        0        其它

全局定义结构体
struct node
{ 
	datatype vertex[N];
	int arc[N][N];
	int degree_out[N];  //顶点的出度 
	int degree_in[N];   //顶点的入度  
}mGraph;
邻接矩阵创建图

1.确定图的顶点个数和边的个数;
2. 输入顶点信息;
3. 初始化邻接矩阵;
4. 依次输入每条边存储在邻接矩阵arc中;
     4.1 输入边依附的两个顶点的序号i, j;
     4.2 将邻接矩阵的第i行第j列的元素值置为1;
     4.3 将邻接矩阵的第j行第i列的元素值置为1;

代码如下:

int creatGraph(int vertexnum,int vertexarc)//创建邻接矩阵
{
	int l,k,j,i;
	printf("请输入四个顶点的值n");
	for(int i=0;i 
邻接矩阵输出图 

代码如下:

void display(int vertexnum,int vertexarc)//输出图的邻接矩阵 
{
	int i,j;
	puts("输出顶点的值");
	for(i=0;i 
基于邻接矩阵深度优先遍历 

⑴ 访问顶点v;
⑵ 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;
⑶ 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

代码如下:

int  DFSTraversel(int v)//基于邻接矩阵的深度优先遍历  
{
     printf("%d ",mGraph.vertex[v]); 
     visited [v]=1;
     for (int j=0; j 
基于邻接矩阵的广度优先遍历 

⑴ 访问顶点v;
⑵ 依次访问v的各个未被访问的邻接点v1, v2, …, vk;
⑶ 分别从v1,v2,…,vk出发依次访问它们未被访问的邻接点,并使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问。直至图中所有与顶点v有路径相通的顶点都被访问到。

代码如下:

int DFSTraversel2(int v)//基于邻接矩阵的广度优先遍历
{
	printf("基于邻接矩阵的广度优先遍历"); 
	int rear=-1,front=-1;
	int Q[vertexnum];
	printf("%d ",mGraph.vertex[v]);
	visited[v]=1;
	Q[++rear]=v;
	while(front!=rear)
	{
		v=Q[++front];
		for(i=0;i 
  • 如何求顶点 i 的所有邻接点?

将数组中第 i 行元素扫描一遍,若arc[i][j]为1,则顶点 j 为顶点 i 的邻接点。

  • 有向图的邻接矩阵一定不对称吗?

不一定,例如有向完全图。

  • 如何判断从顶点 i 到顶点 j 是否存在边?

测试邻接矩阵中相应位置的元素arc[i][j]是否为1。

邻接表实现图的存储结构
  • 图的邻接矩阵存储结构的空间复杂度?

 假设图G有n个顶点e条边,则存储该图需要O(n2) 。

  • 如果为稀疏图则会出现什么现象?

邻接表存储的基本思想:对于图的每个顶点vi,将所有邻接于vi的顶点链成一个单链表,称为顶点vi的边表(对于有向图则称为出边表),所有边表的头指针和存储顶点信息的一维数组构成了顶点表。

  • 边表中的结点表示什么?

每个结点对应图中的一条边,邻接表的空间复杂度为O(n+2e)。

  • 如何求顶点 i 的度?

顶点i的边表中结点的个数。

  • 如何判断顶点 i 和顶点 j之间是否存在边?

测试顶点 i 的边表中是否存在终点为 j 的结点。

  • 如何求顶点 i 的出度?

顶点 i 的出边表中结点的个数。

  • 如何求顶点 i 的入度?

各顶点的出边表中以顶点 i 为终点的结点个数。

  • 如何求顶点 i 的所有邻接点?

遍历顶点 i 的边表,该边表中的所有终点都是顶点 i 的邻接点。

定义邻接表结点
typedef struct ArcNode
{    int adjvex;  
     struct ArcNode *next;
}Arcnode;
struct VertexNode 
{
      datatype  vertex;
      Arcnode *firstedge;
      int degree_out;   //顶点的出度 
      int degree_in;    //顶点的入度 
} adjlist[N];
创建邻接表

1. 确定图的顶点个数和边的个数;
2. 输入顶点信息,初始化该顶点的边表;
3. 依次输入边的信息并存储在边表中;
     3.1  输入边所依附的两个顶点的序号i和j;
     3.2  生成邻接点序号为j的边表结点s;
     3.3 将结点s插入到第i个边表的头部;

代码如下:

int ALgraph(int vertexnum,int vertexarc)//邻接表的创建
 {
 	Arcnode *p;
 	puts("请输入四个顶点的值");
	for(i=0;iadjvex=l;
		p->next=adjlist[k].firstedge;
		adjlist[k].firstedge=p;
	}
 } 
输出邻接表

代码如下:

void displayAlgraph(int vertexnum)//邻接表的输出 
{	
	ArcNode *p;
	for(i=0;iadjvex);
			printf("(%d,%d)  ",adjlist[i].vertex,adjlist[p->adjvex].vertex);
			p=p->next;
		}
		printf("n");
	}
} 
基于邻接表的深度优先遍历

⑴ 访问顶点v;
⑵ 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;
⑶ 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

代码如下:

int DFSTraverse(int v)//基于邻接表的深度优先遍历
{
	Arcnode *p;
	p=adjlist[v].firstedge;
	printf("%d ",adjlist[v].vertex);
	visited[v]=1;
	while(p)
	{
		j=p->adjvex;
		if(visited[j]==0)
		DFSTraverse(j);
		p=p->next;
	}
	
} 
基于邻接表的广度优先遍历

⑴ 访问顶点v;
⑵ 依次访问v的各个未被访问的邻接点v1, v2, …, vk;
⑶ 分别从v1,v2,…,vk出发依次访问它们未被访问的邻接点,并使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问。直至图中所有与顶点v有路径相通的顶点都被访问到。

代码如下:

int DFSTraverse2(int v)//基于邻接表的广度优先输出
{
	Arcnode *p;
	int rear=-1,front=-1;
	int Q[vertexnum];
	printf("%d ",adjlist[v].vertex);
	visited[v]=1;
	Q[++rear]=v;
	while(rear!=front)
	{
		v=Q[++front];
		p=adjlist[v].firstedge;
		while(p)
		{
			j=p->adjvex;
			if(visited[j]==0)
			{
				printf("%d ",adjlist[j].vertex);
				visited[j]=1;
				Q[++rear]=j;
			}
			p=p->next;
		} 
	}
} 
主函数
main()
{menu();
	printf("请输入你要选择的功能: ");
	int n;
	scanf("%d",&n);
	while(n)
	{
	switch(n)
	{ 
	case 0:break;
	case 1:creatGraph(vertexnum,vertexarc); //创建图的邻接矩阵结构
		break;
	case 2:ALgraph(vertexnum,vertexarc);// 创建图的邻接表结构 
		break;
	case 3:display(vertexnum,vertexarc);//输出图的邻接矩阵 
		break;
	case 4:displayAlgraph(vertexnum);//输出图的邻接表
		break;
 	case 5:puts("深度优先遍历输出");
	 		DFSTraversel(0);//基于邻接矩阵的深度优先遍历 
			putchar('n');//换行 
			initVisited(vertexnum);//初始化visited数组
		break;
	case 6:	DFSTraversel2(0);//基于邻接矩阵的广度优先遍历
 			putchar('n');//换行
			initVisited(vertexnum);//初始化visited数组
		break;
	case 7:
			puts("深度优先遍历输出");	
			DFSTraverse(0);//基于邻接表的深度优先遍历
			putchar('n');//换行
			initVisited(vertexnum);//初始化visited数组
		break;
	case 8:puts("广度优先遍历输出"); 
			DFSTraverse2(0);//基于邻接表的广度优先遍历
 			putchar('n');//换行
			initVisited(vertexnum);//初始化visited数组
		break;
	}
	menu();
	scanf("%d",&n);
	}
}
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/913467.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号