网络的带权邻接表存储结构
时间: 2024-08-13 20:05:18 浏览: 54
网络的带权邻接表是一种图数据结构,常用于表示和操作带有权重的图,例如在图算法中。它主要由以下几个部分组成:
1. **顶点(Vertices)**:每个顶点代表图中的一个实体,通常是一个数字或字符串标识。
2. **边(Edges)**:每条边表示两个顶点之间的连接,包括起点和终点,以及一个权重值。权重可以是任意实数,比如表示距离、成本等。
3. **邻接表**:对于每个顶点,维护一个列表,称为邻接表,其中包含所有与其相连的边及其权重。邻接表可以是链式结构,每个边作为一个节点,包含指向起点、终点和权重的信息。
- 对于无向图,邻接表会为每个顶点维护双向边。
- 对于有向图,邻接表可能只记录出度信息,即从某顶点出发的所有边。
这种存储结构的优势在于:
- **空间效率**:如果图是稀疏的(即边的数量远小于可能的顶点对数量),带权邻接表可以节省大量空间,因为只存储实际存在的边。
- **操作效率**:对于查找从一个顶点到另一个顶点的最短路径、加权遍历等操作,通过直接访问邻接表非常高效。
相关问题
创建如上有向带权图的邻接矩阵和邻接表存储结构并输出;分别在邻接矩阵和邻接表存储结构下求图中每个顶点的入度;分别在邻接矩阵和邻接表存储结构下对图进行深度和广度优先遍历。
为了方便起见,我先给出图的具体表示,如下所示:
![有向带权图](https://i.imgur.com/mv5FbZC.png)
1. 邻接矩阵存储结构及入度计算
邻接矩阵是一种二维数组,其中行和列表示图中的节点,数组中的值表示相应节点之间的边的权重。我们可以用 0 和 1 表示是否存在边,用正整数或者浮点数表示边的权重。对于本题中的图,邻接矩阵如下:
```
A B C D E F
A 0 1 0 0 1 0
B 0 0 1 0 0 1
C 0 0 0 1 0 1
D 0 0 0 0 0 1
E 0 0 0 0 0 1
F 0 0 0 0 0 0
```
其中,第 i 行第 j 列的值表示从节点 i 到节点 j 是否存在一条边。例如,第 1 行第 2 列的值为 1,表示从节点 A 到节点 B 存在一条边。
计算每个节点的入度时,我们需要遍历整个邻接矩阵,统计每个节点在所有边中作为终点的次数。对于本题中的图,各个节点的入度如下:
```
A: 0
B: 1
C: 1
D: 2
E: 2
F: 3
```
2. 邻接表存储结构及入度计算
邻接表是一种链表,用于表示图中的节点以及每个节点相邻的节点。对于每个节点,我们可以用一个链表存储所有以该节点为起点的边,链表中的每个元素包括一个指向终点节点的指针以及边的权重。对于本题中的图,邻接表如下:
```
A -> (B, 1) -> (E, 2)
B -> (C, 3) -> (F, 4)
C -> (D, 5) -> (F, 6)
D -> (F, 7)
E -> (F, 8)
F ->
```
其中,箭头表示指针,例如 A -> (B, 1) 表示从节点 A 到节点 B 存在一条权重为 1 的边。
计算每个节点的入度时,我们需要遍历整个邻接表,统计每个节点在所有以其他节点为起点的边中作为终点的次数。对于本题中的图,各个节点的入度如下:
```
A: 0
B: 1
C: 1
D: 2
E: 2
F: 3
```
3. 邻接矩阵存储结构下的深度优先遍历
深度优先遍历是一种图遍历方式,从起点节点开始,沿着一条路径一直遍历到终点节点,然后回溯到之前的节点,继续遍历其他路径。具体实现时,我们可以用递归函数来实现。对于本题中的图,从节点 A 开始进行深度优先遍历的结果如下:
```
A -> B -> C -> D -> F -> E
```
其中,箭头表示遍历的顺序。
4. 邻接表存储结构下的深度优先遍历
邻接表存储结构下的深度优先遍历与邻接矩阵存储结构下的深度优先遍历类似,只是遍历时需要访问每个节点相邻的节点。具体实现时,我们可以用递归函数来实现。对于本题中的图,从节点 A 开始进行深度优先遍历的结果如下:
```
A -> B -> C -> D -> F -> E
```
其中,箭头表示遍历的顺序。
5. 邻接矩阵存储结构下的广度优先遍历
广度优先遍历是一种图遍历方式,从起点节点开始,按照距离起点的距离递增的顺序依次遍历所有节点。具体实现时,我们可以用一个队列来存储需要遍历的节点。对于本题中的图,从节点 A 开始进行广度优先遍历的结果如下:
```
A -> B -> E -> C -> F -> D
```
其中,箭头表示遍历的顺序。
6. 邻接表存储结构下的广度优先遍历
邻接表存储结构下的广度优先遍历与邻接矩阵存储结构下的广度优先遍历类似,只是遍历时需要访问每个节点相邻的节点。具体实现时,我们可以用一个队列来存储需要遍历的节点。对于本题中的图,从节点 A 开始进行广度优先遍历的结果如下:
```
A -> B -> E -> C -> F -> D
```
其中,箭头表示遍历的顺序。
写一段c语言代码并实现以下功能:创建有向带权图的邻接矩阵和邻接表存储结构并输出;分别在邻接矩阵和邻接表存储结构下求图中每个顶点的入度;分别在邻接矩阵和邻接表存储结构下对图进行深度和广度优先遍历。
好的,以下是一段实现您要求功能的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 100 // 最大顶点数
// 边结构体
typedef struct EdgeNode {
int adjvex; // 相邻节点编号
int weight; // 边的权重
struct EdgeNode *next; // 下一个边节点
} EdgeNode;
// 顶点结构体
typedef struct VertexNode {
int data; // 顶点数据
EdgeNode *first_edge; // 第一条边节点
} VertexNode;
// 邻接表
typedef struct {
VertexNode adj_list[MAX_VERTEX_NUM]; // 顶点数组
int vertex_num; // 顶点数
int edge_num; // 边数
} GraphAdjList;
// 邻接矩阵
typedef struct {
int adj_matrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵
int vertex_num; // 顶点数
int edge_num; // 边数
} GraphAdjMatrix;
// 初始化邻接表
void initGraphAdjList(GraphAdjList *graph) {
int i;
for (i = 0; i < MAX_VERTEX_NUM; i++) {
graph->adj_list[i].data = 0;
graph->adj_list[i].first_edge = NULL;
}
graph->vertex_num = 0;
graph->edge_num = 0;
}
// 添加边到邻接表
void addEdgeToList(GraphAdjList *graph, int start, int end, int weight) {
EdgeNode *new_edge = (EdgeNode *)malloc(sizeof(EdgeNode));
new_edge->adjvex = end;
new_edge->weight = weight;
new_edge->next = graph->adj_list[start].first_edge;
graph->adj_list[start].first_edge = new_edge;
graph->edge_num++;
}
// 初始化邻接矩阵
void initGraphAdjMatrix(GraphAdjMatrix *graph) {
int i, j;
for (i = 0; i < MAX_VERTEX_NUM; i++) {
for (j = 0; j < MAX_VERTEX_NUM; j++) {
graph->adj_matrix[i][j] = 0;
}
}
graph->vertex_num = 0;
graph->edge_num = 0;
}
// 添加边到邻接矩阵
void addEdgeToMatrix(GraphAdjMatrix *graph, int start, int end, int weight) {
graph->adj_matrix[start][end] = weight;
graph->edge_num++;
}
// 创建有向带权图
void createGraph(GraphAdjList *graph_list, GraphAdjMatrix *graph_matrix) {
int i, start, end, weight;
printf("请输入图的顶点数和边数(用空格隔开):");
scanf("%d %d", &graph_list->vertex_num, &graph_list->edge_num);
graph_matrix->vertex_num = graph_list->vertex_num;
for (i = 0; i < graph_list->edge_num; i++) {
printf("请输入第%d条边的起点、终点和权重(用空格隔开):", i+1);
scanf("%d %d %d", &start, &end, &weight);
addEdgeToList(graph_list, start, end, weight);
addEdgeToMatrix(graph_matrix, start, end, weight);
}
}
// 输出邻接表
void printGraphAdjList(GraphAdjList graph) {
int i;
EdgeNode *p;
for (i = 0; i < graph.vertex_num; i++) {
printf("%d -> ", graph.adj_list[i].data);
p = graph.adj_list[i].first_edge;
while (p != NULL) {
printf("%d(%d) -> ", p->adjvex, p->weight);
p = p->next;
}
printf("NULL\n");
}
}
// 输出邻接矩阵
void printGraphAdjMatrix(GraphAdjMatrix graph) {
int i, j;
for (i = 0; i < graph.vertex_num; i++) {
for (j = 0; j < graph.vertex_num; j++) {
printf("%d ", graph.adj_matrix[i][j]);
}
printf("\n");
}
}
// 求每个顶点的入度(邻接矩阵)
void getInDegreeMatrix(GraphAdjMatrix graph, int *in_degree) {
int i, j;
for (i = 0; i < graph.vertex_num; i++) {
in_degree[i] = 0;
for (j = 0; j < graph.vertex_num; j++) {
if (graph.adj_matrix[j][i] != 0) {
in_degree[i]++;
}
}
}
}
// 求每个顶点的入度(邻接表)
void getInDegreeList(GraphAdjList graph, int *in_degree) {
int i;
EdgeNode *p;
for (i = 0; i < graph.vertex_num; i++) {
in_degree[i] = 0;
}
for (i = 0; i < graph.vertex_num; i++) {
p = graph.adj_list[i].first_edge;
while (p != NULL) {
in_degree[p->adjvex]++;
p = p->next;
}
}
}
// 深度优先遍历(邻接矩阵)
void dfsMatrix(GraphAdjMatrix graph, int start, int *visited) {
int i;
visited[start] = 1;
printf("%d -> ", start);
for (i = 0; i < graph.vertex_num; i++) {
if (graph.adj_matrix[start][i] != 0 && !visited[i]) {
dfsMatrix(graph, i, visited);
}
}
}
// 深度优先遍历(邻接表)
void dfsList(GraphAdjList graph, int start, int *visited) {
EdgeNode *p;
visited[start] = 1;
printf("%d -> ", start);
p = graph.adj_list[start].first_edge;
while (p != NULL) {
if (!visited[p->adjvex]) {
dfsList(graph, p->adjvex, visited);
}
p = p->next;
}
}
// 广度优先遍历(邻接矩阵)
void bfsMatrix(GraphAdjMatrix graph, int start, int *visited) {
int i, queue[MAX_VERTEX_NUM], front = 0, rear = 0;
visited[start] = 1;
printf("%d -> ", start);
queue[rear++] = start;
while (front != rear) {
start = queue[front++];
for (i = 0; i < graph.vertex_num; i++) {
if (graph.adj_matrix[start][i] != 0 && !visited[i]) {
visited[i] = 1;
printf("%d -> ", i);
queue[rear++] = i;
}
}
}
}
// 广度优先遍历(邻接表)
void bfsList(GraphAdjList graph, int start, int *visited) {
int i, queue[MAX_VERTEX_NUM], front = 0, rear = 0;
EdgeNode *p;
visited[start] = 1;
printf("%d -> ", start);
queue[rear++] = start;
while (front != rear) {
start = queue[front++];
p = graph.adj_list[start].first_edge;
while (p != NULL) {
if (!visited[p->adjvex]) {
visited[p->adjvex] = 1;
printf("%d -> ", p->adjvex);
queue[rear++] = p->adjvex;
}
p = p->next;
}
}
}
int main() {
GraphAdjList graph_list;
GraphAdjMatrix graph_matrix;
int in_degree[MAX_VERTEX_NUM], visited[MAX_VERTEX_NUM];
int i;
initGraphAdjList(&graph_list);
initGraphAdjMatrix(&graph_matrix);
createGraph(&graph_list, &graph_matrix);
printf("邻接表:\n");
printGraphAdjList(graph_list);
printf("邻接矩阵:\n");
printGraphAdjMatrix(graph_matrix);
printf("邻接矩阵中每个顶点的入度:\n");
getInDegreeMatrix(graph_matrix, in_degree);
for (i = 0; i < graph_matrix.vertex_num; i++) {
printf("%d ", in_degree[i]);
}
printf("\n");
printf("邻接表中每个顶点的入度:\n");
getInDegreeList(graph_list, in_degree);
for (i = 0; i < graph_list.vertex_num; i++) {
printf("%d ", in_degree[i]);
}
printf("\n");
printf("邻接矩阵深度优先遍历:\n");
for (i = 0; i < graph_matrix.vertex_num; i++) {
visited[i] = 0;
}
for (i = 0; i < graph_matrix.vertex_num; i++) {
if (!visited[i]) {
dfsMatrix(graph_matrix, i, visited);
}
}
printf("NULL\n");
printf("邻接表深度优先遍历:\n");
for (i = 0; i < graph_list.vertex_num; i++) {
visited[i] = 0;
}
for (i = 0; i < graph_list.vertex_num; i++) {
if (!visited[i]) {
dfsList(graph_list, i, visited);
}
}
printf("NULL\n");
printf("邻接矩阵广度优先遍历:\n");
for (i = 0; i < graph_matrix.vertex_num; i++) {
visited[i] = 0;
}
for (i = 0; i < graph_matrix.vertex_num; i++) {
if (!visited[i]) {
bfsMatrix(graph_matrix, i, visited);
}
}
printf("NULL\n");
printf("邻接表广度优先遍历:\n");
for (i = 0; i < graph_list.vertex_num; i++) {
visited[i] = 0;
}
for (i = 0; i < graph_list.vertex_num; i++) {
if (!visited[i]) {
bfsList(graph_list, i, visited);
}
}
printf("NULL\n");
return 0;
}
```
您可以直接复制上述代码并编译运行,即可得到您想要的结果。
阅读全文