采用邻接矩阵或邻接表存储结构来建立有向图或无向图,分别实现图的深度优先遍历递归和非递归算法以及广度优先遍历算法。
时间: 2024-12-18 14:22:19 浏览: 0
邻接表或者邻接矩阵为存储结构实现连通无向图的深度优先和广度优先遍历
3星 · 编辑精心推荐
在图论中,我们通常使用邻接矩阵或邻接表这两种数据结构来表示有向图或无向图。它们各有优势:
**邻接矩阵**:
- 邻接矩阵是一个二维数组,其中每个元素表示两个顶点之间是否存在边。如果(i, j)位置为1(或true),则表示从顶点i到顶点j有一条边;否则没有边。
- **深度优先遍历 (DFS)**: 对于无向图,我们可以用邻接矩阵实现DFS的递归版本,从任一顶点开始,访问其所有相邻节点,然后递归地对未访问过的邻居进行相同操作。非递归版本可以用栈辅助。
- 递归版(无向图): 从一个起始顶点v出发,`dfs(v)`,遍历所有相连的顶点。
- 非递归版(无向图): 使用栈,先入后出的特点保证了搜索顺序。
**邻接表**:
- 邻接表则是一系列链表,每个顶点对应一个链表,链表中的节点包含指向与其相连的其他顶点的引用。
- **深度优先遍历 (DFS)**: 递归版与邻接矩阵类似,非递归版本同样使用栈,但查找邻居更简单,因为直接遍历链表即可。
- 递归版(有向/无向图): 对于有向图,只访问当前顶点的邻居。
- 非递归版(有向/无向图): 用栈存储待访问的顶点及其前驱,每次取出一个顶点并访问它的所有邻居。
**广度优先遍历 (BFS)**:
- 无论邻接矩阵还是邻接表,都可以高效地执行BFS。BFS从起点开始逐层扩展,先访问距离起点最近的节点。
- 递归版: 不适用于大规模图,因为递归调用可能导致栈溢出。
- 非递归版: 通常使用队列,依次处理每一层的节点。
以下是邻接表实现的DFS和BFS示例(C++):
```cpp
// DFS递归版 (无向图)
void dfsRec(vector<vector<int>>& adj, int v, vector<bool>& visited) {
visited[v] = true;
for (int neighbor : adj[v]) {
if (!visited[neighbor])
dfsRec(adj, neighbor, visited);
}
}
// DFS非递归版 (无向图)
void dfsNonRec(vector<vector<int>>& adj, int v, vector<bool>& visited, stack<int>& s) {
visited[v] = true;
s.push(v);
while (!s.empty()) {
int u = s.top();
s.pop();
cout << u << " ";
for (int neighbor : adj[u]) {
if (!visited[neighbor])
s.push(neighbor);
}
}
}
// BFS (无向图)
void bfs(vector<vector<int>>& adj, int start) {
queue<int> q;
vector<bool> visited(adj.size(), false);
q.push(start);
visited[start] = true;
while (!q.empty()) {
int v = q.front(); q.pop();
cout << v << " "; // 输出节点
for (int neighbor : adj[v]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push(neighbor);
}
}
}
}
```
阅读全文