作为一个数据结构学习的新手,这篇文章也算是笔记了,请根据目录食用
目录
方法一(结合“二、用邻接矩阵表示法创建有向图结合”中图片一)
方法二(结合“二、用邻接矩阵表示法创建有向图结合”中图片二)
一、存储结构
typedef struct Mgraph {
int arcs[Maxnum][Maxnum]; //邻接矩阵
Vertextype vexs[Maxnum]; //顶点表
int vexnum, arcnum; //图当前的顶点数和弧数
} Mgraph;
二、用邻接矩阵表示法创建有向图
int Locate(Mgraph g, Vertextype v) {
int i;
for (i = 0; i < g.vexnum; i++)
if (g.vexs[i] == v)
return i;
}
//创建邻接矩阵
void Creat_Mgraph(Mgraph &g) {
Vertextype vi, vj;
int i, j, k;
printf("请输入顶点个数和弧的个数:\n");
scanf("%d %d", &g.vexnum, &g.arcnum);
getchar();
printf("请输入顶点数据:\n");
for (i = 0; i < g.vexnum; i++)
scanf("%c", &g.vexs[i]);
getchar();
for (i = 0; i < g.vexnum; i++)
for (j = 0; j < g.vexnum; j++)
g.arcs[i][j] = 0;
for (i = 0; i < g.arcnum; i++) {
printf("请输入顶点信息:\n");
scanf("%c%c", &vi, &vj);
getchar();
j = Locate(g, vi); //定位行数
k = Locate(g, vj); //定位列数
g.arcs[j][k] = 1;
}
}
【对应的图】
【图片一】
【创建完成的邻接矩阵】
【图片二】
三、用邻接矩阵实现深度优先搜索
方法一(结合“二、用邻接矩阵表示法创建有向图结合”中图片一)
【思路】从一个结点出发,从它的第一个结点一股劲地向下探索(深度搜索),探索完后返回到下一个邻结点,接着一股劲地向下探索(这就很符合递归的思路,一次探到底,然后返回去进行下一次探索)
//确定第一个邻结点
int FirstAdjVex(MGraph g, int v) {
int j;
for (j = 0; j < g.vexnum; j++)
if (g.arcs[v][j].adj == 1)
return j;
return -1;
}
//确定下一个邻结点
int NextAdjVex(MGraph g, int v, int w) {
int j;
for (j = w + 1; j < g.vexnum; j++)
if (g.arcs[v][j].adj == 1)
return j;
return -1;
}
//循环实现深度优先搜索
void dfs_M(MGraph g, int v) {
int i, j, w;
visited[v] = 1;
printf("%c", g.vxes[v]);
for (w = FirstAdjVex(g, v); w >= 0; w = NextAdjVex(g, v, w))
if (!visited[w])
dfs_M(g, w);
}
方法二(结合“二、用邻接矩阵表示法创建有向图结合”中图片二)
【思路】思路还是和方法一的一样,只不过少写俩函数。由于邻接矩阵中的1标志的就是邻结点的信息,所以就没必要再设置函数去确定第一个邻结点和下一个邻结点的位置
//深度优先遍历
void dfs_M(Mgraph g, int v) {
int i, j, w;
visited[v] = 1;
printf("%c", g.vexs[v]);
for (j = 0; j < g.vexnum; j++)
if (!visited[j] && g.arcs[v][j] == 1)
dfs_M(g, j);
}
//防止出现非连通图的情况
void graph_traver(Mgraph g) {
int i;
for (i = 0; i < g.vexnum; i++)
visited[i] = 0;
for (i = 0; i < g.vexnum; i++)
if (visited[i] == 0)
dfs_M(g, i);
}
四、用邻接矩阵实现广度优先搜索
void bfs_M(Mgraph g, int i) {
int j, u;
int Q[Maxnum];
int rear, front;
rear = front = 0;
printf("%c", g.vexs[i]);
visited[i] = 1;
rear++;
Q[rear] = i;
while (rear != front) {
front++;
u = Q[front];
for (j = 0; j < g.vexnum; j++) {
if (g.arcs[u][j] == 1 && visited[j] == 0) {
visited[j] = 1;
rear++;
Q[rear] = j;
printf("%c", g.vexs[j]);
}//if
}//for
}//while
}
【思路】和二叉树的层序遍历思路很像,从一个结点出发,入队,出队,通过内循环将其邻结点入队,接着将队首元素出队,进行内循环将邻结点入队,重复上述步骤直至队空结束
五、邻接矩阵实现度、入度、出度的统计
【基本概念】
【度】顶点v的度是指和v相关联的边的数目
【入度】以顶点v为头的弧的个数,即指向v的结点的个数
【出度】以顶点v为尾的弧的个数,即v指向的结点的个数
【思路】每一行数字的和对应的就是该结点的出度,每一列对应的数字的和对应的就是该结点的入度
void Count(Mgraph g) {
int i = 0, j, r[Maxnum], c[Maxnum];
for (i = 0; i < g.vexnum; i++){
c[i] = 0;
r[i] = 0;
}
for (i = 0; i < g.vexnum; i++)
for (j = 0; j < g.vexnum; j++)
if (g.arcs[i][j] == 1)
c[i] += 1;
for (j = 0; j < g.vexnum; j++)
for (i = 0; i < g.vexnum; i++)
if (g.arcs[i][j] == 1)
r[j] += 1;
for (i = 0; i < g.vexnum; i++) {
printf("%d:", i + 1);
printf("%d %d %d\n", r[i], c[i], r[i] + c[i]);
}
}
【进一步思考】其实在存储结构中加入入度出度两个数据,在建立邻接矩阵输入数据的的时候就可以将入度出度统计出来,但是会比较浪费空间。