实验三 图的基本操作
一、实验目的
掌握图的常用存储结构和基本操作,用邻接矩阵或邻接表作为存储方式实现图
的创建、遍历及相关操作。
二、实验内容
(1)、实现图的邻接表或邻接矩阵表示,并创建图;
(2)、对邻接表或邻接矩阵表示的图实现深度优先遍历;
三、实验原理、方法和手段
图的概念抽象于大量现实世界问题的图形表示方式,具有广泛的应用背景。作
为一种逻辑结构,主要有邻接矩阵和邻接表两种存储方式。图的遍历与树的遍历很
类似,也是从某个顶点出发,沿某条搜索路径对图中的所以结点进行访问,每个结
点访问而且仅访问一次。根据搜索的不同规则,遍历图的方法分为两种:深度优先
遍历和广度优先遍历,前者借助于堆栈完成,而后者则借助于队列,可以看成一种
层次遍历方法。深度优先遍历的基本思想:
① 选择一个起始点出发,并访问之;
②一次从起始点的未访问过的邻接点出发,深度遍历图,直到图中与起始点有
路径相通的顶点都被访问过为止;
③如此时图中尚有顶点未被访问过,则另选图中一个未访问过的顶点作起始点,
重复上述过程,直到所有顶点被访问过为止。
#include <iostream>
using namespace std;
#define MAXVEX 100
#define INFINITY 65535
typedef struct {
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
} MGraph; //定义了一个结构体MGraph
//包含了顶点数组vexs和邻接矩阵arc,以及图的顶点数numVertexes和边数numEdges。
int visited[MAXVEX]; //定义了一个标志数组visited,用于标记每个顶点是否被访问过
void DFS(MGraph G, int i) {
int j;
visited[i] = 1;
cout << G.vexs[i] << " ";
for (j = G.numVertexes - 1; j >= 0; j--) {
if (G.arc[i][j] == 1 && !visited[j]) {
DFS(G, j);
}
}
} // 定义了一个递归函数DFS,它的参数是图G和当前顶点i。
int main() {
MGraph G;
int i, j, k;
cout << "请输入顶点数和边数:";
cin >> G.numVertexes >> G.numEdges;
for (i = 0; i < G.numVertexes; i++) {
cout << "请输入第" << i + 1 << "个顶点:";
cin >> G.vexs[i];
}
for (i = 0; i < G.numVertexes; i++) {
for (j = 0; j < G.numVertexes; j++) {
G.arc[i][j] = 0;
}
}
for (k = 0; k < G.numEdges; k++) {
cout << "请输入边(vi, vj)上的下标i和j:";
cin >> i >> j;
G.arc[i][j] = 1;
G.arc[j][i] = G.arc[i][j];
}
cout << "深度优先遍历序列为:";
for (i = 0; i < G.numVertexes; i++) {
visited[i] = 0;
}
memset(visited, 0, sizeof(visited)); // 初始化所有节点为未访问状态
DFS(G, 2); // 从节点2开始DFS
cout << endl;
return 0;
}
结果:
实验结果分析:
实验中,尝试使用邻接矩阵实现的深度优先搜索(DFS)算法来遍历图。根据代码和邻接表,发现实际的遍历结果(0 3 4 1 2)与预期的结果(2 1 0 3 4)不符。原因在于:
1. **DFS算法的实现**:DFS实现从顶点0开始遍历,并且在内层循环中按顶点编号的升序进行访问。
2. **邻接矩阵的构建**:邻接矩阵输入可能没有正确反映邻接表所描述的图结构。
为了得到预期的遍历顺序,需要调整DFS算法以从特定节点开始,并确保邻接矩阵正确地表示了图的结构。DFS算法的结果受到遍历起始点和邻接矩阵构建方式的影响。
思考题
图的广度优先遍历(BFS):
1. **初始化队列**:创建一个队列用于存放待访问的节点。
2. **选择起始点**:选择一个起点,将其加入队列,并标记为已访问。
3. **遍历节点**:只要队列不为空,进行以下操作:
- 从队列中弹出一个节点,并访问它。
- 将所有未访问的邻接节点加入队列,并标记为已访问。