如何建立带权的邻接表
时间: 2023-11-27 22:10:08 浏览: 63
建立带权的邻接表需要在存储结构体中增加一个表示边权值的成员变量,同时在添加边时也要记录边的权值。以下是一个示例代码:
```
struct Edge {
int to; // 表示连接的节点编号
int weight; // 表示边的权值
Edge* next; // 指向下一个邻接节点的指针
};
struct Node {
int id; // 节点编号
Edge* next; // 指向第一个邻接节点的指针
};
// 邻接表带权的数据结构
vector<Node> graph;
// 添加一条带权边
void addEdge(int u, int v, int w) {
Edge* e = new Edge;
e->to = v;
e->weight = w;
e->next = graph[u].next;
graph[u].next = e;
}
```
以上代码中,`Edge` 结构体中增加了一个成员变量 `weight`,用于表示边的权值。在添加边时,除了记录连接的节点编号外,还需要记录边的权值,即将 `w` 赋值给 `Edge` 结构体中的 `weight` 成员变量。
建立带权的邻接表的过程与建立普通邻接表的过程类似,只需在添加边时增加权值的记录即可。
相关问题
网络的带权邻接表存储结构
网络的带权邻接表是一种图数据结构,常用于表示和操作带有权重的图,例如在图算法中。它主要由以下几个部分组成:
1. **顶点(Vertices)**:每个顶点代表图中的一个实体,通常是一个数字或字符串标识。
2. **边(Edges)**:每条边表示两个顶点之间的连接,包括起点和终点,以及一个权重值。权重可以是任意实数,比如表示距离、成本等。
3. **邻接表**:对于每个顶点,维护一个列表,称为邻接表,其中包含所有与其相连的边及其权重。邻接表可以是链式结构,每个边作为一个节点,包含指向起点、终点和权重的信息。
- 对于无向图,邻接表会为每个顶点维护双向边。
- 对于有向图,邻接表可能只记录出度信息,即从某顶点出发的所有边。
这种存储结构的优势在于:
- **空间效率**:如果图是稀疏的(即边的数量远小于可能的顶点对数量),带权邻接表可以节省大量空间,因为只存储实际存在的边。
- **操作效率**:对于查找从一个顶点到另一个顶点的最短路径、加权遍历等操作,通过直接访问邻接表非常高效。
图的带权邻接表广度优先遍历c语言
以下是使用带权邻接表实现图的广度优先遍历的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 100 // 最大顶点数
typedef int Vertex; // 顶点类型为整型
typedef int WeightType; // 权重类型为整型
// 边结构体
typedef struct ENode {
Vertex v1, v2; // 有向边<v1, v2>
WeightType weight; // 权重
}ENode;
// 邻接点结构体
typedef struct AdjVNode {
Vertex adjv; // 邻接点下标
WeightType weight; // 权重
struct AdjVNode* next; // 指向下一个邻接点的指针
}AdjVNode;
// 顶点结构体
typedef struct Vnode {
AdjVNode* firstedge; // 指向第一个邻接点的指针
}Vnode, AdjList[MaxVertexNum];
// 图结构体
typedef struct GNode {
int Nv; // 顶点数
int Ne; // 边数
AdjList G; // 邻接表
}GNode, *PtrToGNode;
typedef PtrToGNode Graph;
int visited[MaxVertexNum]; // 访问标记数组
// 创建图并初始化
Graph CreateGraph(int VertexNum)
{
Vertex v;
Graph G = (Graph)malloc(sizeof(GNode));
G->Nv = VertexNum;
G->Ne = 0;
for (v = 0; v < G->Nv; v++)
G->G[v].firstedge = NULL;
return G;
}
// 插入边
void InsertEdge(Graph G, ENode* e)
{
AdjVNode* newnode;
// 为v1插入边<v1, v2>
newnode = (AdjVNode*)malloc(sizeof(AdjVNode));
newnode->adjv = e->v2;
newnode->weight = e->weight;
newnode->next = G->G[e->v1].firstedge;
G->G[e->v1].firstedge = newnode;
// 为v2插入边<v2, v1>(无向图)
newnode = (AdjVNode*)malloc(sizeof(AdjVNode));
newnode->adjv = e->v1;
newnode->weight = e->weight;
newnode->next = G->G[e->v2].firstedge;
G->G[e->v2].firstedge = newnode;
}
// 构造图
Graph BuildGraph()
{
Graph G;
ENode* e;
Vertex v;
int Nv, i;
printf("请输入顶点数: ");
scanf("%d", &Nv);
G = CreateGraph(Nv);
printf("请输入边数: ");
scanf("%d", &(G->Ne));
if (G->Ne != 0) {
e = (ENode*)malloc(sizeof(ENode));
printf("请输入每条边的起点、终点和权重: ");
for (i = 0; i < G->Ne; i++) {
scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
InsertEdge(G, e);
}
}
// 如果顶点有数据的话,读入数据
for (v = 0; v < G->Nv; v++)
scanf("%d", &(G->G[v].data));
return G;
}
// 遍历顶点v所在的连通块
void BFS(Graph G, Vertex v)
{
AdjVNode* W;
Queue Q = CreateQueue(); // 创建空队列
printf("访问顶点 %d\n", v);
visited[v] = 1; // 标记为已访问
Enqueue(Q, v); // 将v入队列
while (!IsEmpty(Q)) { // 只要队列不空
v = Dequeue(Q); // 将队首顶点出队列
for (W = G->G[v].firstedge; W; W = W->next) { // 对v的每个邻接点W->adjv
if (!visited[W->adjv]) { // 若W未被访问
printf("访问顶点 %d\n", W->adjv);
visited[W->adjv] = 1; // 标记为已访问
Enqueue(Q, W->adjv); // 将W入队列
}
}
}
}
// 遍历图
void BFSTraverse(Graph G)
{
Vertex v;
for (v = 0; v < G->Nv; v++)
visited[v] = 0; // 初始化访问标记数组
for (v = 0; v < G->Nv; v++) {
if (!visited[v]) // 若顶点v未被访问
BFS(G, v); // 访问顶点v所在的连通块
}
}
```
其中,`ENode`表示边结构体,包含两个顶点和权重;`AdjVNode`表示邻接点结构体,包含邻接点下标、权重和指向下一个邻接点的指针;`Vnode`表示顶点结构体,包含指向第一个邻接点的指针;`AdjList`表示邻接表,是一个大小为`MaxVertexNum`的`Vnode`数组;`GNode`表示图结构体,包含顶点数、边数和邻接表。`CreateGraph`函数创建图并初始化,`InsertEdge`函数插入边,`BuildGraph`函数构造图,`BFS`函数遍历顶点v所在的连通块,`BFSTraverse`函数遍历图。
阅读全文