设计一个有向图和一个无向图,建立图的邻接矩阵或邻接表的存储结构,完成有向图和无向图的dfs(深度优先遍历)和bfs(广度优先遍历)的操作。(有向图采用邻接矩阵存储,无向图采用邻接表存储)
时间: 2023-05-31 09:19:38 浏览: 176
建立图的邻接矩阵或邻接表存储并在此基础上实现图的深度优先遍历和广度优先遍历.doc
5星 · 资源好评率100%
### 回答1:
有向图邻接矩阵存储结构:
假设有向图有5个顶点,顶点分别为V1、V2、V3、V4、V5,边分别为(V1,V2)、(V1,V4)、(V2,V3)、(V2,V5)、(V3,V4)、(V4,V5),邻接矩阵存储结构如下:
V1 V2 V3 V4 V5
V1 1 1
V2 1 1
V3 1
V4 1
V5
有向图dfs操作:
从V1开始遍历,先访问V1,再访问V2,再访问V3,再访问V4,最后访问V5。
有向图bfs操作:
从V1开始遍历,先访问V1,再访问V2,再访问V4,再访问V3,最后访问V5。
无向图邻接表存储结构:
假设无向图有5个顶点,顶点分别为V1、V2、V3、V4、V5,边分别为(V1,V2)、(V1,V4)、(V2,V3)、(V2,V5)、(V3,V4)、(V4,V5),邻接表存储结构如下:
V1 -> V2 -> V4
V2 -> V1 -> V3 -> V5
V3 -> V2 -> V4
V4 -> V1 -> V3 -> V5
V5 -> V2 -> V4
无向图dfs操作:
从V1开始遍历,先访问V1,再访问V2,再访问V3,再访问V4,最后访问V5。
无向图bfs操作:
从V1开始遍历,先访问V1,再访问V2,再访问V4,再访问V3,最后访问V5。
### 回答2:
设计一个有向图和一个无向图的邻接矩阵和邻接表
有向图的邻接矩阵:
```
1 2 3 4
1 0 1 1 0
2 0 0 1 0
3 0 0 0 1
4 0 0 0 0
```
有向图的邻接表:
```
1->2->3
2->3
3->4
4->null
```
无向图的邻接矩阵:
```
1 2 3 4
1 0 1 1 0
2 1 0 1 1
3 1 1 0 0
4 0 1 0 0
```
无向图的邻接表:
```
1->2->3
2->1->3->4
3->1->2
4->2
```
DFS深度优先遍历(有向图):
按照某个节点开始,访问该节点,递归访问其邻居节点,回溯到上一个节点继续遍历其邻居节点。使用栈实现,先访问的节点先入栈。
算法步骤:
1. 从起点开始遍历,并将其标记为已访问
2. 将该节点入栈
3. 将该节点的邻居节点依次入栈,并递归访问其邻居节点
4. 如果该节点没有邻居节点或其邻居节点都被标记为已访问,则将该节点弹出栈,回溯到上一节点
DFS深度优先遍历(无向图):
与有向图的遍历类似,只是将有向图中的入度和出度改为度数,在遍历时需考虑重复访问的情况。使用栈实现,先访问的节点先入栈。
算法步骤:
1. 从起点开始遍历,并将其标记为已访问
2. 将该节点入栈
3. 将该节点的未访问过的邻居节点依次入栈,并递归访问其邻居节点
4. 如果该节点没有未访问的邻居节点,则将该节点弹出栈,回溯到上一节点
BFS广度优先遍历(有向图):
从一个起点开始遍历,先访问它的邻居节点,再访问邻居节点的邻居节点,以此类推,直至访问完整张图。使用队列实现,先访问的节点先进队列。
算法步骤:
1. 将起点入队,并将其标记为已访问
2. 取出队首节点,并依次访问其未访问的邻居节点,将其标记为已访问,并入队
3. 重复步骤2,直至队列为空
BFS广度优先遍历(无向图):
与有向图的遍历类似,只是将有向图中的入度和出度改为度数,在遍历时需考虑重复访问的情况。使用队列实现,先访问的节点先进队列。
算法步骤:
1. 将起点入队并将其标记为已访问
2. 取出队首节点的未访问过的邻居节点,并依次访问,将其标记为已访问,并入队
3. 重复步骤2,直至队列为空
邻接矩阵和邻接表的存储方式不同,但是深度优先遍历和广度优先遍历的算法思路是相同的,只是数据结构的不同导致了实现的细节有所不同。在实际应用中,对于较大规模的图,邻接表的存储方式更有效率。
### 回答3:
一、有向图的邻接矩阵存储结构
我们设计一个有向图,表示5个城市之间的直达道路情况,如下所示:
1 -- 2 -- 3
| \/ |
| /\ |
4 -- 5
邻接矩阵是有向图的常见存储结构,它用一个二维数组来表示图中各个节点之间的关系。定义邻接矩阵G[i][j]表示从i到j有一条边,则有向图的邻接矩阵为:
1 2 3 4 5
1 0 1 0 1 1
2 0 0 1 0 1
3 0 0 0 0 0
4 0 0 0 0 1
5 0 0 0 0 0
其中,0表示没有边相连,1表示有边相连。
邻接矩阵的优点在于可以快速判断两个节点之间是否存在连通关系,但需要占用大量的存储空间。
有向图的DFS和BFS的实现过程与无向图类似,具体实现方法可参考下面的代码示例。
二、无向图的邻接表存储结构
以同样的城市道路为例,我们可以将这个图构建成无向图,如下所示:
1 -- 2 -- 3
| | |
4 -- 5 |
邻接表是一种常见的无向图存储结构,它是通过链表来表示一个节点的相邻节点的集合。用一个数组来存放所有的节点,每个节点通过一个链表来存储它的所有相邻节点。邻接表的定义如下:
```
struct AdjListNode {
int dest;
struct AdjListNode* next;
};
struct AdjList {
struct AdjListNode* head;
};
class Graph {
int V;
struct AdjList* adj;
public:
Graph(int V) {
this->V = V;
adj = new AdjList[V];
for(int i=0;i<V;i++)
adj[i].head = NULL;
}
void addEdge(int src, int dest) {
AdjListNode* newNode = new AdjListNode;
newNode->dest = dest;
newNode->next = adj[src].head;
adj[src].head = newNode;
newNode = new AdjListNode;
newNode->dest = src;
newNode->next = adj[dest].head;
adj[dest].head = newNode;
}
void BFS(int s);
void DFS(int s);
};
void Graph::BFS(int s) {
bool visited[V];
for(int i=0;i<V;i++) visited[i] = false;
queue<int> q;
visited[s] = true;
q.push(s);
while(!q.empty()) {
int v = q.front();
cout << v << " ";
q.pop();
for(AdjListNode* p = adj[v].head;p != NULL;p=p->next) {
int w = p->dest;
if(!visited[w]) {
visited[w] = true;
q.push(w);
}
}
}
}
void dfs(int v, bool visited[], struct AdjList adj[]) {
visited[v] = true;
cout << v << " ";
for(AdjListNode* p=adj[v].head;p!=NULL;p=p->next) {
int w = p->dest;
if(!visited[w])
dfs(w,visited,adj);
}
}
void Graph::DFS(int s) {
bool visited[V];
for(int i=0;i<V;i++) visited[i] = false;
dfs(s,visited,adj);
}
```
至此,我们已经完成了无向图的DFS和BFS的实现过程。通过邻接表可以大大节省存储空间,但查找是否存在连通关系时要遍历链表,耗时较长。
阅读全文