一、存储结构
#include <stdio.h>
#include <stdlib.h>
#define INFINT 9999999 //最大int值,即无穷
#define MAXVertexNum 100 //最大顶点数
typedef char VerTexType; //顶点对应的数据类型
typedef int ArcType; //边对应的数据类型
typedef struct{
VerTexType vexs[MAXVertexNum]; //顶点表
ArcType arcs[MAXVertexNum][MAXVertexNum]; //邻接矩阵,边表
int vexnum,arcnum; //图的当前点数和边数
bool isUndirected; //记录是否为无向图
}MGraph;
二、初始化操作
对顶点数和边数初始化为0
同时考虑顶点自身的边数为0
初始所有顶点之间没有变,设为无穷∞
void InitGraph(MGraph &G) {
int i, j;
// 设置图的当前顶点数和边数
G.vexnum = 0; // 初始化顶点数为0
G.arcnum = 0; // 初始化边数为0
G.isUndirected = 1; //默认为无向图
// 初始化邻接矩阵,将所有边的值设为INFINITY
for (i = 0; i < MAXVertexNum; i++) {
for (j = 0; j < MAXVertexNum; j++) {
if (i == j) {
G.arcs[i][j] = 0; // 顶点到自身的边为0
} else {
G.arcs[i][j] = INFINT; // 无穷大表示没有边
}
}
}
}
三、插入顶点操作
// 插入顶点函数
void InsertVertex(MGraph &G, VerTexType v) {
if (G.vexnum >= MAXVertexNum) {
printf("顶点表已满");
return;
}
// 在顶点数组中插入新顶点
G.vexs[G.vexnum] = v;
G.vexnum++;
return;
}
四、插入边操作
如果是无向图,则ij位置交替再赋值一次
if(G.isUndirected) G.arcs[j][i] = weight;
// 插入边函数
int AddEdge(MGraph &G, VerTexType v1, VerTexType v2, ArcType weight=1) {
int i = -1, j = -1;
// 查找顶点v1和v2在顶点表中的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == v1) {
i = k;
}
if (G.vexs[k] == v2) {
j = k;
}
}
// 如果找到顶点v1和v2
if (i != -1 && j != -1) {
G.arcs[i][j] = weight; // 插入边,v1 -> v2
if(G.isUndirected) G.arcs[j][i] = weight; // 如果是无向图,插入边,v2 -> v1
G.arcnum++;
return 1;
} else {
printf("顶点不存在");
return 0;
}
}
五、输出查看邻接矩阵
// 查看邻接矩阵的函数
void DisplayAdjMatrix(MGraph &G) {
int i, j;
// 打印顶点
printf("顶点表");
printf(" ");
for (i = 0; i < G.vexnum; i++) {
printf("%c ", G.vexs[i]);
}
printf("\n");
// 打印邻接矩阵
for (i = 0; i < G.vexnum; i++) {
printf("%c: ", G.vexs[i]);
for (j = 0; j < G.vexnum; j++) {
if (G.arcs[i][j] == INFINT) {
printf("INF ");
} else {
printf("%d ", G.arcs[i][j]);
}
}
printf("\n");
}
}
六、主函数
int main() {
//=====================================================
//无向图
//========
MGraph G; // 创建一个图
InitGraph(G); // 初始化图
// 插入顶点
InsertVertex(G, 'A');
InsertVertex(G, 'B');
InsertVertex(G, 'C');
InsertVertex(G, 'D');
InsertVertex(G, 'E');
// 插入边
InsertEdge(G, 'A', 'B');
InsertEdge(G, 'A', 'D');
InsertEdge(G, 'A', 'C');
InsertEdge(G, 'B', 'E');
InsertEdge(G, 'C', 'D');
DisplayAdjMatrix(G);
return 0;
//=====================================================
}
七、判断图是否存在边<x,y>或(y,x)
有向图和无向图算法一致
// 判断图是否存在边<x,y>或(y,x)
int Adjacent(MGraph G, VerTexType x, VerTexType y) {
int i = -1, j = -1;
// 查找顶点 x 和 y 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) i = k;
if (G.vexs[k] == y) j = k;
}
// 如果顶点存在并且存在边
if (i != -1 && j != -1 && (G.arcs[i][j] != INFINT || G.arcs[j][i] != INFINT)) {
return 1; // 存在边
}
return 0; // 不存在边
}
八、列出图中节点 x 的邻接的边
考虑有向图的入边邻接点
// 列出图中节点 x 的邻接的边
void Neighbors(MGraph G, VerTexType x) {
int i = -1;
// 查找顶点 x 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) {
i = k;
break;
}
}
if (i == -1) {
printf("顶点 %c 不存在\n", x);
return;
}
// 输出与顶点 x 相邻的所有顶点
printf("顶点 %c 的邻接的边: ", x);
for (int j = 0; j < G.vexnum; j++) {
if (G.arcs[i][j] != INFINT && i != j) {
if(G.isUndirected==1) printf("(%c,%c) ", G.vexs[i],G.vexs[j]);
if(G.isUndirected==0) printf("<%c,%c> ", G.vexs[i],G.vexs[j]);
}
else (G.isUndirected==0 && G.arcs[j][i] != INFINT && i != j) { //考虑有向图的入边邻接点
printf("<%c,%c>", G.vexs[j],G.vexs[i]);
}
}
printf("\n");
}
九、删除顶点操作
DeleteVertex(G,c) 在图中删除顶点x
有向图比无向图操作略有增加,主要体现在计算边数的时候
将图分成四块区域
按象限顺序,第二象限为不动组,
第一象限和第三象限为左移或上移一格组,
第四象限为先上移再左移组
操作示意图如下
// 删除顶点函数
void DeleteVertex(MGraph &G, VerTexType c) {
int i, j;
// 查找顶点 c 的索引
for (i = 0; i < G.vexnum; i++) {
if (G.vexs[i] == c) break;
}
if (i == G.vexnum) {
printf("顶点 %c 不存在\n", c);
return;
}
// 删除顶点 c 对应的行和列
for (j = 0; j < G.vexnum - 1; j++) {
G.vexs[j+i] = G.vexs[j + i + 1];
for (int k = i; k < G.vexnum; k++) {
if(j<i) {
if(j<i && k==i && (G.arcs[j][k]!=INFINT && G.arcs[j][k]!=0)) G.arcnum--;
// 如果是有向图,则需要判断双向
if(G.isUndirected==0 &&j<i && k==i && (G.arcs[k][j]!=INFINT && G.arcs[k][j]!=0)) G.arcnum--;
G.arcs[j][k] = G.arcs[j][k+1];
G.arcs[k][j] = G.arcs[k+1][j];
}
if(j>=i){
if(j==i && (G.arcs[j][k+1]!=INFINT && G.arcs[j][k+1]!=0)) G.arcnum--;
//如果是有向图,则需要判断双向
if(G.isUndirected==0 && j==i && (G.arcs[k+1][j]!=INFINT && G.arcs[k+1][j]!=0)) G.arcnum--;
if(G.isUndirected==0 && j==i && k==G.vexnum-1 && (G.arcs[k+1][j]!=INFINT && G.arcs[k+1][j]!=0)) G.arcnum--;
G.arcs[j][k+1] = G.arcs[j + 1][k+1];
G.arcs[j][k] = G.arcs[j][k+1];
}
}
}
G.vexnum--;
}
十、删除边操作
如果是无向图,则ij位置交替再删除一次,即删除两个方向的边
if(G.isUndirected) G.arcs[j][i] = INFINT;
// 删除边函数
void RemoveEdge(MGraph &G, VerTexType x, VerTexType y) {
int i = -1, j = -1;
// 查找顶点 x 和 y 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) i = k;
if (G.vexs[k] == y) j = k;
}
if (i != -1 && j != -1) {
G.arcs[i][j] = INFINT;
if(G.isUndirected) G.arcs[j][i] = INFINT; // 无向图需要删除两个方向的边
G.arcnum--;
} else {
printf("边 (%c, %c) 不存在\n", x, y);
}
}
十一、求顶点 x 的第一个邻接点
求图中顶点x的第一个邻接点,若有则返回定点好,若x没有邻接点或图中不存在x,则返回-1
// 求顶点 x 的第一个邻接点
int FirstNeighbor(MGraph G, VerTexType x) {
int i = -1;
// 查找顶点 x 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) {
i = k;
break;
}
}
if (i == -1) {
printf("顶点 %c 不存在\n", x);
return -1;
}
// 查找第一个邻接点
for (int j = 0; j < G.vexnum; j++) {
if (G.arcs[i][j] != INFINT && i != j) {
return j; // 返回邻接点的索引
}
//如果是有向图,第一个邻接点可能源自于入边
if (G.isUndirected==0 &&G.arcs[j][i] != INFINT && i != j) {
return j; // 返回邻接点的索引
}
}
return -1; // 没有邻接点
}
十二、求顶点 x 的下一个邻接点
假设图中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
// 求顶点 x 的下一个邻接点
int NextNeighbor(MGraph G, VerTexType x, VerTexType y) {
int i = -1, j = -1;
// 查找顶点 x 和 y 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) i = k;
if (G.vexs[k] == y) j = k;
}
if (i == -1 || j == -1) {
printf("顶点 %c 或 %c 不存在\n", x, y);
return -1;
}
// 查找下一个邻接点
for (int k = j + 1; k < G.vexnum; k++) {
if (G.arcs[i][k] != INFINT && i != k) {
return k;
}
//如果是有向图,则下一个邻接点可能源自于入边
if (G.isUndirected==0 && G.arcs[k][i] != INFINT && i != k) {
return k;
}
}
return -1; // 没有下一个邻接点
}
十三、获取边的权值
// 获取边的权值
ArcType Get_edge_value(MGraph G, VerTexType x, VerTexType y) {
int i = -1, j = -1;
// 查找顶点 x 和 y 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) i = k;
if (G.vexs[k] == y) j = k;
}
if (i != -1 && j != -1) {
return G.arcs[i][j];
}
printf("边 (%c, %c) 不存在\n", x, y);
return -1;
}
十四、设置边的权值
// 设置边的权值
void Set_edge_value(MGraph &G, VerTexType x, VerTexType y, ArcType v) {
int i = -1, j = -1;
// 查找顶点 x 和 y 的索引
for (int k = 0; k < G.vexnum; k++) {
if (G.vexs[k] == x) i = k;
if (G.vexs[k] == y) j = k;
}
if (i != -1 && j != -1) {
G.arcs[i][j] = v;
if(G.isUndirected) G.arcs[j][i] = v; // 无向图需设置两个方向
} else {
printf("边 (%c, %c) 不存在\n", x, y);
}
}

1217

被折叠的 条评论
为什么被折叠?



