之前我们介绍了图的几种存储方式和一些初始化之类的简单操作,今天给大家展示关于邻接矩阵的基本操作.
Ajacent(G,x,y):判断图G是否存在边<x,y>或(x,y)
Neighbor(G,x):判断图中与结点x相邻的边
InsertVertex(G,x):在图中插入顶点x
DeleteVertex(G,x):在图中删除顶点x
AddEdge(G,x,y):若无向边(x,y)或有向边<x,y>不存在,则向图中添加该边
RemoveEdge(G,x,y):若无向边(x,y)或有向边<x,y>存在,则从图G中删除该边
FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1
NextNeighBor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
具体的代码实现:
//邻接矩阵的构建
#include<stdio.h>
#include<stdbool.h>
#include<limits.h>
#define VertexNum 5 //假设是5个顶点组成的无向图
typedef struct
{
char Ver[VertexNum];//顶点cha的集合
bool Edge[VertexNum][VertexNum];//邻接矩阵边表,bool类型只存放0和1
int vexnum;//顶点数
}MGraph;
//初始化邻接矩阵
void InitGraph(MGraph* M)
{
M->vexnum = 0;//初始化为0
int i, j;
//初始化顶点
for (i = 0; i < VertexNum; i++)
{
M->Ver[i] = '\0';
}
//初始化邻接矩阵
for (i = 0; i < VertexNum; i++)
{
for (j = 0; j < VertexNum; j++)
{
M->Edge[i][j] = 0;//初始化矩阵全为零
}
}
return;
}
//创建顶点
bool EnVertex(MGraph* M)
{
if (M->vexnum >= VertexNum)
return false;//空间已满
int i = 0;
while (i < VertexNum)
{
M->Ver[i] = 'A' + i;
M->vexnum++;
i++;
}
return true;
}
//创建边
bool EnEdge(MGraph* M)
{
if (M->vexnum <= 1)
return false;//非图或者只有一个顶点无法创建边
//创建A的边
M->Edge[0][1] = 1;
M->Edge[0][2] = 1;
M->Edge[0][3] = 1;
//创建B的边
M->Edge[1][0] = 1;
M->Edge[1][3] = 1;
//创建C的边
M->Edge[2][0] = 1;
//创建D的边
M->Edge[3][0] = 1;
M->Edge[3][1] = 1;
M->Edge[3][4] = 1;
//创建E的边
M->Edge[4][3] = 1;
return true;
}
//判断图G是否存在边(x,y)
int Adjacent(MGraph* M, char ch1, char ch2)
{
if (M->vexnum == 0)
return INT_MIN;//非图
if (M->vexnum == 1)
return INT_MIN;//一个顶点无边
int index1 = -1;//存储ch1在顶点数组中的位置
int index2 = -1;//存储ch2在顶点数组中的位置
int i = 0;
//找出ch1与ch2的下标
for (i; i < VertexNum; i++)
{
if (M->Ver[i] == ch1)
index1 = i;
if (M->Ver[i] == ch2)
index2 = i;
}
if (index1 == -1 || index2 == -1)
{
printf("顶点不合法\n");
return INT_MIN;
}
//判断ch1与ch2在矩阵中的值
if (M->Edge[index1][index2] == 1 && M->Edge[index2][index1] == 1)
return 1;
else
return 0;
return INT_MIN;
}
//列出图M中与顶点x相邻的边
bool Neighbors(MGraph* M, char ch)
{
if (M->vexnum == 0)
return false;//图不合法
if (M->vexnum == 1)
return false;//只有一个顶点
int index = -1;//求该顶点的下标
int i;
int flag = 0;//标记
for (i = 0; i < VertexNum; i++)
if (M->Ver[i] == ch)
index = i;
if (index == -1)
return false;//该结点不存在
//当ch与其他顶点存在边
for (i = 0; i < VertexNum; i++)
{
if (M->Edge[index][i] == 1)
{
flag = 1;
printf("%c和%c存在边\n", ch, M->Ver[i]);
}
}
if (flag == 0)
printf("%c不存在边\n", ch);
return true;
}
//从图中删除顶点
bool DeleteVertex(MGraph* M, char ch)
{
if (M->vexnum == 0)
return false;//非法图
if (M->vexnum == 1)
return false;//只有一个顶点
//求出ch的下标
int index = -1;
int i = 0;
for (i = 0; i < VertexNum; i++)
if (M->Ver[i] == ch)
index = i;
if (index == -1)
return false;//未找到该顶点
//令该顶点所在行和列置为0
for (i = 0; i < VertexNum; i++)
{
M->Edge[index][i] = 0;
M->Edge[i][index] = 0;
}
return true;
}
//添加边
bool AddEdge(MGraph* M, char ch1, char ch2)
{
if (M->vexnum == 0)
return false;//非法图
if (M->vexnum == 1)
return false;//只有一个顶点
int flag;
flag = Adjacent(M, ch1, ch2);
if (flag == INT_MIN)
return false;//非法图
else if (flag == 1)
return false;//已经存在边
else
{//获取两个顶点的下标
int index1 = -1;
int index2 = -1;
int i;
for (i = 0; i < VertexNum; i++)
{
if (M->Ver[i] == ch1)
index1 = i;
if (M->Ver[i] == ch2)
index2 = i;
}
M->Edge[index1][index2] = M->Edge[index2][index1] = 1;
printf("%c和%c 连接成功\n",ch1,ch2);
}
return true;
}
//删除边
bool RemoveEdge(MGraph* M, char ch1, char ch2)
{
int flag = Adjacent(M, ch1, ch2);
if (flag == INT_MIN)
return false;//图不合法
else if (flag == 0)
return false;//两个顶点之间没有边
else
{
//获取顶点
int index1, index2;
int i;
for (i = 0; i < VertexNum; i++)
{
if (M->Ver[i] == ch1)
index1 = i;
if (M->Ver[i] = ch2)
index2 = i;
}
M->Edge[index1][index2] = 0;
printf("%c与%c之间已经删除边\n",ch1, ch2);
}
return true;
}
//获取顶点的第一个邻接点的顶点号
char FirstNeighbor(MGraph* M, char ch)
{
if (M->vexnum == 0)
return '\0';//非法图
if (M->vexnum == 1)
return '\0';//只有一个顶点
//获取该顶点在数组中的位置
int index = -1;
int i;
char first = '\0';
for (i = 0; i < VertexNum; i++)
{
if (M->Ver[i] == ch)
index = i;
}
printf("\n");
if (index == -1)
return '\0';//无该顶点
for (i = 0; i < VertexNum; i++)
if (M->Edge[index][i] == 1)
{
first = M->Ver[i];
return first;
}
return -1;
}
char NextNeightbor(MGraph* M, char ch1, char ch2)
{
if (M->vexnum == 0)
return '\0';//非法图
if (M->vexnum == 1)
return '\0';//只有一个顶点
//获取两个顶点的下标
int index1 = -1;
int index2 = -1;
char Next = '\0';
int i = 0;
for (i; i < VertexNum; i++)
{
if (M->Ver[i] == ch1)
index1 = i;
if (M->Ver[i] == ch2)
index2 = i;
}
for (i = index2 + 1; i < VertexNum; i++)
{
if (M->Edge[index1][i] == 1)
{
Next = M->Ver[i];
return Next;
}
}
return -1;
}
//打印图
void PrintGraph(MGraph* M)
{
int i = 0;
int j = 0;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d", M->Edge[i][j]);
}
printf("\n");
}
}
int main()
{
MGraph M;//定义一个指向图的变量
InitGraph(&M);//初始化图
EnVertex(&M);//插入顶点
EnEdge(&M);//创建边
//图的具体操作
//判断图M是否存在边(x,y)
Adjacent(&M, 'A', 'E');
//列出图M中与顶点x相邻的边
Neighbors(&M, 'A');
//从图中删除顶点
//DeleteVertex(&M, 'C');
//若无向边(x,y)不存在,则向图G中删除该边
AddEdge(&M, 'D', 'C');
//若无向边(x,y)存在,则从图M中删除该边
//RemoveEdge(&M, 'D', 'C');
//求图M中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1
char ch = FirstNeighbor(&M, 'A');
printf("A的第一个邻接点为%c\n",ch);
//假设图M中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
char c = NextNeightbor(&M, 'A', 'B');
printf("A下一个邻接点的下一个为%c", c);
//打印图
//PrintGraph(&M);
return 0;
}
我们这个创建的是无向图的具体操作,有向图与无向图大部分类似,极个别可能有差别,大家在创建的时候需要留意.