一、程序
/*
项目名称:邻接矩阵存储图
编译环境: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++;
}
}
二、以无向网为例的结果
![](https://i-blog.csdnimg.cn/blog_migrate/217a95e27e5f20d6aeeb3354b3a3cc08.png)