本文只有代码,介绍了有关图(邻接矩阵)的基本操作。
已经过调试没有很大问题。
如有错误,还请批评指正。
一、图的数组(邻接矩阵)存储表示:
#include
#include
#include
/* 状态信息 */
typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
/* 图的数组(邻接矩阵)存储表示 */
typedef int VRType; //顶点关系类型
typedef char InfoType; //弧类型
typedef char VertexType; //顶点类型
#define INFINITY 0 //最大值∞
#define MAX_VERTEX_NUM 20 //最大顶点个数
typedef enum { DG, DN, UDG, UDN } GraphKind;//{有向图,有向网,无向图,无向网}
typedef struct ArcCell
{
VRType adj; //VRType是顶点关系类型。对无权图,用1和0表示相邻否;对带权图,则为权值类型
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);/* 构造图CreateGraph(&G) */
Status CreateUDN(MGraph* G);/* 构造无向网CreateUDN(&G) */
Status CreateUDG(MGraph* G);/* 构造无向图CreateUDG(&G) */
Status CreateDN(MGraph* G);/* 构造有向网CreateDN(&G) */
Status CreateDG(MGraph* G);/* 构造有向图CreateDG(&G) */
void PrintGraph(MGraph G);/* 打印图PrintGraph(G) */
Status DestroyGraph(MGraph* G);/* 销毁图DestroyGraph(&G) */
Status LocateVex(MGraph G, VertexType u);/* 若图中存在顶点u,则返回该顶点在图中的位置LocateVex(G, u) */
Status GetVex(MGraph G, VertexType v);/* v是G的某个顶点,返回v的值GetVex(G, v) */
Status PutVex(MGraph* G, VertexType v, VertexType value);/* 对v赋值PutVex(&G, v, value) */
Status FirstAdjVex(MGraph G, VertexType v);/* 返回v的第一个邻接顶点FirstAdjVex(G, v) */
Status NextAdjVex(MGraph G, VertexType v, VertexType w);/* w是v的邻接顶点,返回v相对于w的下一个邻接顶点NextAdjVex(G, v, w) */
Status InsertVex(MGraph* G, VertexType v);/* 在图中增添新顶点InsertVex(&G, v) */
Status DeleteVex(MGraph* G, VertexType v);/* 删除G中顶点v及其相关的弧DeleteVex(&G, v) */
Status InsertArc(MGraph* G, VertexType v, VertexType w, VRType value);/* 在图中增添弧InsertArc(&G, v, w, value) */
Status DeleteArc(MGraph* G, VertexType v, VertexType w);/* 在图中删除弧DeleteArc(&G, v, w) */
/* DFS/BFS使用的全局变量 */
int visited[MAX_VERTEX_NUM];
void DFS(MGraph G, int n);/* 从第n个顶点出发深度优先遍历图DFS(G, n) */
void DFSTraverse(MGraph G);/* 对图G进行深度优先遍历DFSTraverse(G) */
void BFS(MGraph G, int n);/* 从第n个顶点出发广度优先遍历图BFS(G, n) */
void BFSTraverse(MGraph G);/* 对图G进行广度优先遍历BFSTraverse(G) */
1、构造图:
/*---------------------------------------------------------------------------------------
功能:构造图
参数:1、图
输出:OK、ERROR
*/
/* 构造图CreateGraph(&G) */
Status CreateGraph(MGraph* G)
{
printf("1.有向图 2.有向网 3.无向图 4.无向网\n");
printf("请输入要创建表的种类:>");
scanf("%d", &G->kind);
switch (G->kind - 1)
{
case DG:
return CreateDG(G);
case DN:
return CreateDN(G);
case UDG:
return CreateUDG(G);
case UDN:
return CreateUDN(G);
default:
break;
}
return ERROR;
}
2、构造无向网:
/*---------------------------------------------------------------------------------------
功能:构造无向网
参数:1、图指针
输出:OK、ERROR
*/
/* 构造无向网CreateUDN(&G) */
Status CreateUDN(MGraph* G)
{
int i = 0, j = 0, k = 0, w = 0;
char temp = 0;//临时储存
printf("请输入图的顶点个数\n");
scanf("%d", &G->vexnum);
printf("请输入图的弧数\n");
scanf("%d", &G->arcnum);
printf("请输入所有顶点\n");
for (i = 0; i < G->vexnum; i++)
{
temp = getchar(); //储存回车符
scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
}
//进行初始化,赋初值
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;
}
}
char v1, v2;
printf("请输入弧的两个顶点和权值\n");
//对矩阵进行赋值
for (k = 0; k < G->arcnum; k++)
{
temp = getchar();
scanf("%c%c%d", &v1, &v2, &w);
i = LocateVex(*G, v1);
j = LocateVex(*G, v2);
G->arcs[i][j].adj = w;
G->arcs[j][i].adj = w;//对称
}
printf("无向网创建成功!!!\n");
return OK;
}
3、构造无向图:
/*---------------------------------------------------------------------------------------
功能:构造无向图
参数:1、图指针
输出:OK、ERROR
*/
/* 构造无向图CreateUDG(&G) */
Status CreateUDG(MGraph* G)
{
int i = 0, j = 0, k = 0, w = 0;
char temp = 0;//临时储存
printf("请输入图的顶点个数\n");
scanf("%d", &G->vexnum);
printf("请输入图的弧数\n");
scanf("%d", &G->arcnum);
printf("请输入所有顶点\n");
for (i = 0; i < G->vexnum; i++)
{
temp = getchar(); //储存回车符
scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
}
//进行初始化,赋初值
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;
}
}
char v1, v2;
printf("请输入弧的两个顶点\n");
//对矩阵进行赋值
for (k = 0; k < G->arcnum; k++)
{
temp = getchar();
scanf("%c%c", &v1, &v2);
i = LocateVex(*G, v1);
j = LocateVex(*G, v2);
G->arcs[i][j].adj = 1;
G->arcs[j][i].adj = 1;//对称
}
printf("无向图创建成功!!!\n");
return OK;
}
4、构造有向网:
/*---------------------------------------------------------------------------------------
功能:构造有向网
参数:1、图指针
输出:OK、ERROR
*/
/* 构造有向网CreateDN(&G) */
Status CreateDN(MGraph* G)
{
int i = 0, j = 0, k = 0, w = 0;
char temp = 0;//临时储存
printf("请输入图的顶点个数\n");
scanf("%d", &G->vexnum);
printf("请输入图的弧数\n");
scanf("%d", &G->arcnum);
printf("请输入所有顶点\n");
for (i = 0; i < G->vexnum; i++)
{
temp = getchar(); //储存回车符
scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
}
//进行初始化,赋初值
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;
}
}
char v1, v2;
printf("请输入弧的两个顶点(起点-终点)和权值\n");
//对矩阵进行赋值
for (k = 0; k < G->arcnum; k++)
{
temp = getchar();
scanf("%c%c%d", &v1, &v2, &w);
i = LocateVex(*G, v1);
j = LocateVex(*G, v2);
G->arcs[i][j].adj = w;
}
printf("有向网创建成功!!!\n");
return OK;
}
5、构造有向图:
/*---------------------------------------------------------------------------------------
功能:构造有向图
参数:1、图指针
输出:OK、ERROR
*/
/* 构造有向图CreateDG(&G) */
Status CreateDG(MGraph* G)
{
int i = 0, j = 0, k = 0, w = 0;
char temp = 0;//临时储存
printf("请输入图的顶点个数\n");
scanf("%d", &G->vexnum);
printf("请输入图的弧数\n");
scanf("%d", &G->arcnum);
printf("请输入所有顶点\n");
for (i = 0; i < G->vexnum; i++)
{
temp = getchar(); //储存回车符
scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
}
//进行初始化,赋初值
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;
}
}
char v1, v2;
printf("请输入弧的两个顶点(起点-终点)\n");
//对矩阵进行赋值
for (k = 0; k < G->arcnum; k++)
{
temp = getchar();
scanf("%c%c", &v1, &v2);
i = LocateVex(*G, v1);
j = LocateVex(*G, v2);
G->arcs[i][j].adj = 1;
}
printf("有向图创建成功!!!\n");
return OK;
}
6、打印图:
/*---------------------------------------------------------------------------------------
功能:打印图
参数:1、图
输出:空
*/
/* 打印图PrintGraph(G) */
void PrintGraph(MGraph G)
{
int i = 0, j = 0;
for (i = 0; i < G.vexnum; ++i)
{
for (j = 0; j < G.vexnum; ++j)
{
printf("%d ", G.arcs[i][j].adj);
if ((j + 1) % G.vexnum == 0)
printf("\n");
}
}
}
7、销毁图:
/*---------------------------------------------------------------------------------------
功能:销毁图
参数:1、图指针
输出:OK、ERROR
*/
/* 销毁图DestroyGraph(&G) */
Status DestroyGraph(MGraph* G)
{
int i = 0, j = 0;
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;
}
}
G->vexnum = 0;
G->arcnum = 0;
return OK;
}
8、若图中存在顶点u,则返回该顶点在图中的位置:
/*---------------------------------------------------------------------------------------
功能:若图中存在顶点u,则返回该顶点在图中的位置
参数:1、图 2、顶点
输出:顶点位置、FALSE
*/
/* 若图中存在顶点u,则返回该顶点在图中的位置LocateVex(G, u) */
Status LocateVex(MGraph G, VertexType u)
{
int i = 0;
for (i = 0; i < G.vexnum; i++) {
if (G.vexs[i] == u)
return i;
}
return FALSE;
}
9、v是G的某个顶点,返回v的值:
/*---------------------------------------------------------------------------------------
功能:v是G的某个顶点,返回v的值
参数:1、图 2、顶点
输出:顶点的值、FALSWE
*/
/* v是G的某个顶点,返回v的值GetVex(G, v) */
Status GetVex(MGraph G, VertexType v)
{
int i = 0;
for (i = 0; i < G.vexnum; i++)
{
if (G.vexs[i] == v)
return i;
}
return FALSE;
}
10、对v赋值:
/*---------------------------------------------------------------------------------------
功能:对v赋值
参数:1、图指针 2、顶点 3、值
输出:OK、ERROR
*/
/* 对v赋值PutVex(&G, v, value) */
Status PutVex(MGraph* G, VertexType v, VertexType value)
{
int i = 0;
for (i = 0; i < G->vexnum; i++)
{
if (G->vexs[i] == v)
G->vexs[i] = value;
return OK;
}
return ERROR;
}
11、返回v的第一个邻接顶点的值:
/*---------------------------------------------------------------------------------------
功能:返回v的第一个邻接顶点的值
参数:1、图 2、顶点
输出:顶点、FALSE
*/
/* 返回v的第一个邻接顶点FirstAdjVex(G, v) */
Status FirstAdjVex(MGraph G, VertexType v)
{
int i = 0, j = 0;
i = LocateVex(G, v);
for (j = 0; j < G.vexnum; j++)
{
if (G.arcs[i][j].adj != INFINITY || G.arcs[j][i].adj != INFINITY)
{
return j;
}
}
return FALSE;
}
12、w是v的邻接顶点,返回v相对于w的下一个邻接顶点的值:
/*---------------------------------------------------------------------------------------
功能:w是v的邻接顶点,返回v相对于w的下一个邻接顶点的值
参数:1、图 2、顶点 3、顶点
输出:顶点、FALSE
*/
/* w是v的邻接顶点,返回v相对于w的下一个邻接顶点NextAdjVex(G, v, w) */
Status NextAdjVex(MGraph G, VertexType v, VertexType w)
{
int i = 0, j = 0, n = 0;
i = LocateVex(G, v);
j = LocateVex(G, w);
for (n = j + 1; n < G.vexnum; n++)
{
if (G.arcs[i][n].adj != INFINITY || G.arcs[n][i].adj != INFINITY)
{
return n;
}
}
return FALSE;
}
13、在图中增添新顶点:
/*---------------------------------------------------------------------------------------
功能:在图中增添新顶点
参数:1、图指针 2、顶点
输出:OK、ERROR
*/
/* 在图中增添新顶点InsertVex(&G, v) */
Status InsertVex(MGraph* G, VertexType v)
{
int i = 0;
G->vexnum++;
//更改存储顶点的数组
G->vexs[G->vexnum - 1] = v;
//更改矩阵
for (i = 0; i < G->vexnum; i++)
{
//为矩阵最外层行、列的元素赋初始值
G->arcs[G->vexnum - 1][i].adj = INFINITY;
G->arcs[G->vexnum - 1][i].info = NULL;
G->arcs[i][G->vexnum - 1].adj = INFINITY;
G->arcs[i][G->vexnum - 1].info = NULL;
}
return OK;
}
14、删除G中顶点v及其相关的弧:
/*---------------------------------------------------------------------------------------
功能:删除G中顶点v及其相关的弧
参数:1、图指针 2、顶点
输出:OK、ERROR
*/
/* 删除G中顶点v及其相关的弧DeleteVex(&G, v) */
Status DeleteVex(MGraph* G, VertexType v)
{
int i = 0, j = 0, temp = 0;
i = LocateVex(*G, v);
temp = i;
//更改存储顶点的数组
for (temp; temp < G->vexnum; temp++)
{
G->vexs[temp] = G->vexs[temp + 1];//存储顶点的数组中向前移一位,覆盖要删除的顶点
}
G->vexnum--;
//更改矩阵
for (j = 0; j < G->vexnum + 1; j++)
{
//使矩阵中靠后位置的顶点前移,覆盖被删除的顶点
for (i; i < G->vexnum + 1; i++)
{
G->arcs[j][i] = G->arcs[j][i + 1];
G->arcs[i][j] = G->arcs[i + 1][j];
}
}
for (i = 0; i < G->vexnum; i++)
{
//上一步前移完成后矩阵的最外层的行、列的数据应被清除
G->arcs[G->vexnum][i].adj = INFINITY;
G->arcs[G->vexnum][i].info = NULL;
G->arcs[i][G->vexnum].adj = INFINITY;
G->arcs[i][G->vexnum].info = NULL;
}
return OK;
}
15、在图中增添弧:
/*---------------------------------------------------------------------------------------
功能:在图中增添弧
参数:1、图指针 2、顶点 3、顶点 4、权值
输出:OK、ERROR
*/
/* 在图中增添弧InsertArc(&G, v, w, value) */
Status InsertArc(MGraph* G, VertexType v, VertexType w, VRType value)
{
int i = 0, j = 0;
i = LocateVex(*G, v);
j = LocateVex(*G, w);
G->arcs[i][j].adj = value;
G->arcs[i][j].info = NULL;
G->arcs[j][i].adj = value;
G->arcs[j][i].info = NULL;
return OK;
}
16、在图中删除弧:
/*---------------------------------------------------------------------------------------
功能:在图中删除弧
参数:1、图指针 2、顶点 3、顶点
输出:OK、ERROR
*/
/* 在图中删除弧DeleteArc(&G, v, w) */
Status DeleteArc(MGraph* G, VertexType v, VertexType w)
{
int i = 0, j = 0;
i = LocateVex(*G, v);
j = LocateVex(*G, w);
G->arcs[i][j].adj = INFINITY;
G->arcs[i][j].info = NULL;
G->arcs[j][i].adj = INFINITY;
G->arcs[j][i].info = NULL;
return OK;
}
17、从第n个顶点出发深度优先遍历图:
/*---------------------------------------------------------------------------------------
功能:从第n个顶点出发深度优先遍历图
参数:1、图 2、顶点位置
输出:空
*/
/* 从第n个顶点出发深度优先遍历图DFS(G, n) */
void DFS(MGraph G, int n)
{
int i;
printf("%c", G.vexs[n]);
visited[n] = TRUE;
for (i = 0; i < G.vexnum; i++)
{
if (G.arcs[n][i].adj != INFINITY && visited[i] == FALSE)
{
DFS(G, i);
}
}
}
18、对图G进行深度优先遍历:
/*---------------------------------------------------------------------------------------
功能:对图G进行深度优先遍历
参数:1、图
输出:空
*/
/* 对图G进行深度优先遍历DFSTraverse(G) */
void DFSTraverse(MGraph G)
{
int i = 0, n = 0;
for (i = 0; i < G.vexnum; i++)
{
visited[i] = FALSE; //初始化标志数组
}
for (n = 0; n < G.vexnum; n++)
{
//因为图可能是非联通图,递归访问下一个顶点时可能会中断,因此需要从每一个顶点开始做深度优先遍历
if (visited[n] == FALSE)//判断是否被访问过,未被访问过时访问
{
DFS(G, n);
}
}
}
19、从第n个顶点出发广度优先遍历图:
/*---------------------------------------------------------------------------------------
功能:从第n个顶点出发广度优先遍历图
参数:1、图 2、顶点位置
输出:空
*/
/* 从第n个顶点出发广度优先遍历图BFS(G, n) */
void BFS(MGraph G, int n)
{
int que[MAX_VERTEX_NUM], front = 0, rear = 0;
int i = 0, w = 0;
printf("%c", G.vexs[n]);
visited[n] = TRUE;//访问
rear = (rear + 1) % MAX_VERTEX_NUM;//入队
que[rear] = n;
while (front != rear)
{
//队列不空时
front = (front + 1) % MAX_VERTEX_NUM;//出队
i = que[front];
for (w = FirstAdjVex(G, G.vexs[i]); w != FALSE; w = NextAdjVex(G, G.vexs[i], G.vexs[w]))
{
if (visited[w] == FALSE)
{
visited[w] = TRUE;
printf("%c", G.vexs[w]);//访问
rear = (rear + 1) % MAX_VERTEX_NUM;//入队
que[rear] = w;
}
}
}
}
20、对图G进行广度优先遍历:
/*---------------------------------------------------------------------------------------
功能:对图G进行广度优先遍历
参数:1、图
输出:空
*/
/* 对图G进行广度优先遍历BFSTraverse(G) */
void BFSTraverse(MGraph G)
{
int i = 0, n = 0;
for (i = 0; i < G.vexnum; i++)
{
visited[i] = FALSE; //初始化标志数组
}
for (n = 0; n < G.vexnum; n++)
{
//因为图可能是非联通图,递归访问下一个顶点时可能会中断,因此需要从每一个顶点开始做深度优先遍历
if (visited[n] == FALSE)//判断是否被访问过,未被访问过时访问
{
BFS(G, n);
}
}
}
三、测试主程序(以无向网为例):
int main()
{
MGraph G;
int pos = 0,value = 0;
VertexType v, w,p, q = 0;
CreateGraph(&G);
printf("邻接矩阵:\n");
PrintGraph(G);
v = 'a';
pos = GetVex(G,v);
printf("%c的位置是第%d个\n", v, pos);
v = 'c';
p = FirstAdjVex(G,v);
printf("%c的第一个邻接顶点是%c\n", v, G.vexs[p]);
v = 'c';
w = 'b';
p = NextAdjVex(G,v,w);
printf("%c相对于%c的下一个邻接顶点是%c\n", v, w, G.vexs[p]);
v = 'd';
w = 'e';
value = 1;
if (InsertArc(&G, v, w, value))
{
printf("成功插入<%c,%c,%d>\n", v, w, value);
}
printf("邻接矩阵:\n");
PrintGraph(G);
v = 'd';
w = 'e';
if (DeleteArc(&G, v, w))
{
printf("成功删除弧<%c,%c>\n", v, w);
}
printf("邻接矩阵:\n");
PrintGraph(G);
printf("深度优先遍历DFS:\n");
DFSTraverse(G);
printf("\n");
printf("广度优先遍历BFS:\n");
BFSTraverse(G);
printf("\n");
if (DestroyGraph(&G))
{
printf("销毁成功!!!\n");
}
system("pause");
return 0;
}
四、测试结果: