邻接矩阵存储图的基本操作(不含图的遍历)

一、程序

/*
项目名称:邻接矩阵存储图
编译环境:VC++ 2008
作者相关:。。。
最后修改:2019.10.27
学习目标:1.掌握邻接矩阵存储图的基本操作
注意事项:1.测试所有功能是否正常

遇到问题:

1.结构体ArCell的作用是什么?以及它的成员变量的作用
理解:(1)目的是定义邻接矩阵,矩阵有20*20个位置
(2)每个位置需要判断带权或不带权,带权则填写权值,不带则用-1/1表示相邻否
(3)若相邻可能需要输入该弧(边)的信息
(4)根据(2)(3),矩阵的每个位置需要两个成员变量,这就是结构体的由来

2.CreateUDN中的IncInfo为0各弧不含其它信息是什么意思?
理解:相当于设置一个标志位,用来提示用户是否需要输入信息

3.G.arcs[i][j]={INFINITY,NULL};这个错在哪里?


4.for(i=0;i<G.vexnum;++i)//构造顶点向量
{
printf("请输入第%d个顶点\n",i+1);
scanf("%c",&G.vexs[i]);//输入顶点
}
上面这个循环输出为什么输出两次后才有输入?
解决方案1:scanf读入上一行最后的换行符,相当于滤过了这次手动输入,在前面加getchar()
解决方案2:fflush(stdin)清空标准输入流缓冲区中的内容

5.怎么判断顶点之间是否相邻?
理解:判断邻接矩阵成员的值若为-1则不相邻,1或权值表相邻

6.scanf("%c%c%d",&v1,&v2,&k);
printf("%c",v2);这条语句没有输出,原因是控制台中输入空格会被第二个%c读取


*/


#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"    
#include "stdlib.h"  

#define INFINITY   -1//最大值
#define MAX_VERTEX_NUM 20//最大顶点个数
#define MAX_StrLength  20//最大串长
#define OK       1
#define ERROR    0
#define TRUE     1
#define FALSE    0

typedef enum{DG,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网}
typedef char VertexType;//自定义
typedef bool Status;
typedef int  VRType;//顶点间关系类型(表示邻接否或权值)
typedef char InfoType;//弧段的信息类型

typedef struct ArcCell//该结点字面意思是?
{
	VRType   adj;//1.顶点关系类型。2.对无权图,-1或1表示是否相邻。3.对带权图为权值类型
	InfoType *info;//该弧相关信息的指针

}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵

typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];//顶点向量
	AdjMatrix  arcs;//邻接矩阵
	int        vexnum,arcnum;//图当前的顶点数和弧(边)数
	GraphKind  kind;//图的种类标志
}MGraph;

Status CreateGraph(MGraph &G);

Status DestroyGraph(MGraph &G);

int LocateVex(MGraph &G,VertexType v);

VertexType GetVex(MGraph G,int k);

Status PutVex(MGraph &G,int v,VertexType value);

int FirstAdjVex(MGraph G,VertexType v);

int NextAdjVex(MGraph G,VertexType v,VertexType u);

Status InsertVex(MGraph &G,VertexType v);

Status DeleteVex(MGraph &G,VertexType v);

Status InsertArc(MGraph &G,VertexType v,VertexType w);

Status DeleteArc(MGraph &G,VertexType v,VertexType w);

Status CreateUDN(MGraph &G);

Status CreateUDG(MGraph &G);

Status CreateDN(MGraph &G);

Status CreateDG(MGraph &G);

void ShowMatrix(MGraph G);


int main()
{
	MGraph G;
	VertexType ch='D',value='Q';
	int index=1,Flocation,Nlocation;
	CreateGraph(G);

	printf("vexs中下标为%d对应的顶点为%c\n\n",index,G.vexs[index]);
	PutVex(G,index,value);
	printf("赋值后vexs中下标为%d对应的顶点为%c\n\n",index,G.vexs[index]);
	Flocation=FirstAdjVex(G,G.vexs[index]);
	printf("vexs中%c的第一个邻接顶点为%c\n\n",G.vexs[index],G.vexs[Flocation]);

	Nlocation=NextAdjVex(G,G.vexs[0],G.vexs[1]);
	printf("vexs中%c(相对于%c)的下一个邻接顶点为%c\n\n",G.vexs[0],G.vexs[1],G.vexs[Nlocation]);

	ShowMatrix(G);

	return 0;
}
//采用数组(邻接矩阵)法构造图G
Status CreateGraph(MGraph &G)
{
	printf("请输入要构造的图的种类"
		"[DG(0),DN(1),UDG(2),UDN(3)]\n");
	scanf("%d",&G.kind);
	switch(G.kind)
	{
	case 0: return CreateDG(G);
	case 1: return CreateDN(G);
	case 2: return CreateUDG(G);
	case 3: return CreateUDN(G);
	default :return ERROR;
	}

	return OK;
}
//销毁图
Status DestroyGraph(MGraph &G)
{
	for(int k=0;k<MAX_VERTEX_NUM;k++)
		G.vexs[k]=0;
	for(int i=0;i<G.vexnum;i++)
		for(int j=0;j<G.vexnum;j++)
		{
			if(G.arcs[i][j].info)
			{
				free(G.arcs[i][j].info);
				G.arcs[i][j].info=NULL;
			}
		}
		return OK;
}
//确定v在G中的位置
int LocateVex(MGraph &G,VertexType v)
{
	int i=0;
	while(i<G.vexnum)
	{
		if(G.vexs[i]==v)
			return i;
		else
			++i;
	}
	return -1;//没有返回-1
}
//图G存在,k是某个顶点的序号,返回该顶点的值
VertexType GetVex(MGraph G,int k)
{
	if(k>G.vexnum||k<0)
		return ERROR;

	return G.vexs[k];
}
//图G存在,k是某个顶点的序号,对该项点的值重新赋值
Status PutVex(MGraph &G,int k,VertexType value)
{
	if(k>G.vexnum||k<0)
		return ERROR;

	G.vexs[k]=value;

	return OK;
}
//图G存在,v是G中某个顶点,返回v的第一个邻接顶点,没有则返回空
int FirstAdjVex(MGraph G,VertexType v)
{
	int i;
	int index=LocateVex(G,v);
	for(i=0;i<G.vexnum;i++)
	{
		if(G.arcs[index][i].adj!=-1)
			break;
	}
	if(i==G.vexnum)
		return -1;
	else
		return i;
}
//返回G中顶点v相对于w的下一邻接点
int NextAdjVex(MGraph G,VertexType v,VertexType w)
{
	int iv=LocateVex(G,v);
	int iw=LocateVex(G,w);
	int i;

	for(i=iw+1;i<G.vexnum;i++)
		if(G.arcs[iv][i].adj!=-1)
			break;
	if(i==G.vexnum)
		return -1;
	else
		return i;

}
//在G中增添新顶点v
Status InsertVex(MGraph &G,VertexType v)
{
	G.vexs[G.vexnum]=v;
	G.vexnum++;

	return OK;
}
//删除G中顶点v及其相关的弧
Status DeleteVex(MGraph &G,VertexType v)
{
	int i;
	for(i=0;i<G.vexnum;i++)
		if(G.vexs[i]==v)
			break;
	if(i==G.vexnum)
		return ERROR;
	else
	{
		G.vexs[i]=0;//这样来表示清除
		for(int j=0;j<G.vexnum;j++)
		{
			G.arcs[i][j].adj=-1;//与该点相邻的所有点均设为不相邻
		}
	}
	return OK;
}
//在G中增添弧<v,w>/(v,w),若G是无向的,则增添对称弧(w,v)
Status InsertArc(MGraph &G,VertexType v,VertexType w)
{
	int IncInfo,Weight;
	if(G.kind==0)//有向图
	{
		G.arcs[v][w].adj=1;
		printf("该弧是否含有信息?(0否1是)%d\n",IncInfo);
		scanf("%d",IncInfo);
		fflush(stdin);
		if(IncInfo)
		{
			printf("请输入该弧对应的相关信息:\n");
			fflush(stdin);
			G.arcs[v][w].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
			scanf("%s",&G.arcs[v][w].info);
		}
	}
	if(G.kind==1)//有向网
	{
		printf("请输入该弧对应的权值和弧是否含有信息?(0否1是)%d%d\n",Weight,IncInfo);
		fflush(stdin);
		scanf("%d%d",Weight,IncInfo);
		G.arcs[w][v].adj=Weight;
		if(IncInfo)
		{
			printf("请输入该弧对应的相关信息:\n");
			fflush(stdin);
			G.arcs[v][w].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
			scanf("%s",&G.arcs[v][w].info);
		}
	}
	if(G.kind==2)//无向图
	{
		G.arcs[v][w].adj=1;
		G.arcs[w][v].adj=1;
		printf("该弧是否含有信息?(0否1是)%d\n",IncInfo);
		scanf("%d",IncInfo);
		fflush(stdin);
		if(IncInfo)
		{
			printf("请输入该弧对应的相关信息:\n");
			fflush(stdin);
			G.arcs[v][w].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
			scanf("%s",&G.arcs[v][w].info);
		}
	}
	if(G.kind==3)//无向网
	{
		printf("请输入该弧对应的权值和弧是否含有信息?(0否1是)%d%d\n",Weight,IncInfo);
		fflush(stdin);
		scanf("%d%d",Weight,IncInfo);
		G.arcs[w][v].adj=Weight;
		G.arcs[v][w].adj=Weight;
		if(IncInfo)
		{
			printf("请输入该弧对应的相关信息:\n");
			fflush(stdin);
			G.arcs[v][w].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
			scanf("%s",&G.arcs[v][w].info);
		}
	}

	return OK;
}
//删除弧<v,w>/(v,w),若G是无向的,则删除对称弧(w,v)
Status DeleteArc(MGraph &G,VertexType v,VertexType w)
{
	if(G.kind==0||G.kind==1)//有向图或有向网
	{
		G.arcs[v][w].adj=INFINITY;//假设G.arcs[v][w]代表了有向的弧
		G.arcs[v][w].info=NULL;
	}
	if(G.kind==2||G.kind==3)//无向图或无向网
	{
		G.arcs[v][w].adj=-1;
		G.arcs[v][w].info=NULL;
		G.arcs[w][v].adj=-1;
		G.arcs[w][v].info=NULL;
	}

	return OK;
}

//构造无向网
Status CreateUDN(MGraph &G)
{
	int IncInfo,i,j,k,w;//IncInfo为0表示弧(边)不含信息,当作标志位
	VertexType v1,v2;//项点

	printf("请输入无向网的顶点数和边数及弧是否含信息:\n");
	scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);

	for(i=0;i<G.vexnum;++i)//构造顶点向量
	{
		printf("请输入第%d个顶点\n",i+1);
		getchar();
		scanf("%c",&G.vexs[i]);//输入顶点
	}

	for(i=0;i<G.vexnum;++i)//邻接矩阵的初始化
		for(j=0;j<G.vexnum;++j)
			//G.arcs[i][j]={INFINITY,NULL};///结构体数组成员初始化
		{
			G.arcs[i][j].adj=INFINITY;
			G.arcs[i][j].info=NULL;
		}

		for(k=0;k<G.arcnum;++k)
		{
			printf("请输入第%d条边依附的项点和权值\n",k+1);
			fflush(stdin);//清空标准输入流缓冲区中的内容
			scanf("%c,%c,%d",&v1,&v2,&w);//这里避免读入空格

			i=LocateVex(G,v1);//确定i在G中的下标位置
			j=LocateVex(G,v2);
			G.arcs[i][j].adj=w;//弧(v1,v2)的权值

			if(IncInfo)
			{
				printf("请输入该弧对应的相关信息:\n");
				fflush(stdin);
				G.arcs[i][j].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
				scanf("%s",G.arcs[i][j].info);
			}
			G.arcs[j][i]=G.arcs[i][j];
		}

		return OK;
}
//建立无向图,与无向网的区别就是不带权值
Status CreateUDG(MGraph &G)
{
	int IncInfo,i,j,k;//IncInfo为0表示弧(边)不含信息,当作标志位
	VertexType v1,v2;//项点

	printf("请输入无向图的顶点数和边数及弧是否含信息:\n");
	scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);

	for(i=0;i<G.vexnum;++i)//构造顶点向量
	{
		printf("请输入第%d个顶点\n",i+1);
		fflush(stdin);
		scanf("%c",&G.vexs[i]);//输入顶点
	}

	for(i=0;i<G.vexnum;++i)//邻接矩阵的初始化
		for(j=0;j<G.vexnum;++j)
		{
			G.arcs[i][j].adj=-1;//默认均不相邻
			G.arcs[i][j].info=NULL;
		}

		for(k=0;k<G.arcnum;++k)
		{
			printf("请输入第%d条边依附的项点\n",k+1);
			fflush(stdin);//清空标准输入流缓冲区中的内容
			scanf("%c,%c",&v1,&v2);

			i=LocateVex(G,v1);//确定i在G中的下标位置
			j=LocateVex(G,v2);
			G.arcs[i][j].adj=1;//输入的这两个元素相邻

			if(IncInfo)
			{
				printf("请输入该弧对应的相关信息:\n");
				fflush(stdin);
				G.arcs[i][j].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
				scanf("%s",&G.arcs[i][j].info);
			}
			G.arcs[j][i]=G.arcs[i][j];
		}

		return OK;
}
//有向网的建立
Status CreateDN(MGraph &G)
{
	int IncInfo,i,j,k,w;//IncInfo为0表示弧(边)不含信息,当作标志位
	VertexType v1,v2;//项点

	printf("请输入有向网的顶点数和边数及弧是否含信息:\n");
	scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);

	for(i=0;i<G.vexnum;++i)//构造顶点向量
	{
		printf("请输入第%d个顶点\n",i+1);
		fflush(stdin);
		scanf("%c",&G.vexs[i]);//输入顶点
	}

	for(i=0;i<G.vexnum;++i)//邻接矩阵的初始化
		for(j=0;j<G.vexnum;++j)
		{
			G.arcs[i][j].adj=INFINITY;
			G.arcs[i][j].info=NULL;
		}

		for(k=0;k<G.arcnum;++k)
		{
			printf("请输入第%d条边依附的项点和权值\n",k+1);
			fflush(stdin);//清空标准输入流缓冲区中的内容
			scanf("%c,%c,%d",&v1,&v2,&w);

			i=LocateVex(G,v1);//确定i在G中的下标位置
			j=LocateVex(G,v2);
			G.arcs[i][j].adj=w;//弧(v1,v2)的权值

			if(IncInfo)
			{
				printf("请输入该弧对应的相关信息:\n");
				fflush(stdin);
				G.arcs[i][j].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
				scanf("%s",&G.arcs[i][j].info);
			}
		}

		return OK;
}
//有向图的建立
Status CreateDG(MGraph &G)
{
	int IncInfo,i,j,k;//IncInfo为0表示弧(边)不含信息,当作标志位
	VertexType v1,v2;//项点

	printf("请输入有向图的顶点数和边数及弧是否含信息:\n");
	scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);

	for(i=0;i<G.vexnum;++i)//构造顶点向量
	{
		printf("请输入第%d个顶点\n",i+1);
		fflush(stdin);
		scanf("%c",&G.vexs[i]);//输入顶点
	}

	for(i=0;i<G.vexnum;++i)//邻接矩阵的初始化
		for(j=0;j<G.vexnum;++j)
		{
			G.arcs[i][j].adj=-1;//默认均不相邻
			G.arcs[i][j].info=NULL;
		}

		for(k=0;k<G.arcnum;++k)
		{
			printf("请输入第%d条边依附的项点\n",k+1);
			fflush(stdin);//清空标准输入流缓冲区中的内容
			scanf("%c,%c",&v1,&v2);

			i=LocateVex(G,v1);//确定i在G中的下标位置
			j=LocateVex(G,v2);
			G.arcs[i][j].adj=1;//输入的这两个元素相邻

			if(IncInfo)
			{
				printf("请输入该弧对应的相关信息:\n");
				fflush(stdin);
				G.arcs[i][j].info=(InfoType *)malloc(MAX_StrLength*sizeof(InfoType));
				scanf("%s",&G.arcs[i][j].info);
			}
		}

		return OK;
}

void ShowMatrix(MGraph G)
{
	int flag=0;
	printf("邻接矩阵的内容如下\n");
	for(int i=0;i<G.vexnum;i++)
		for(int j=0;j<G.vexnum;j++)
		{	
			if(flag==G.vexnum)
			{
				printf("\n");
				flag=0;
			}
			printf("%d ",G.arcs[i][j]);
			flag++;
		}
}

二、以无向网为例的结果

发布了62 篇原创文章 · 获赞 9 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Sruggle/article/details/102769795