(写出来仅供随时参考)
邻接矩阵
代码引自my_Dijkstra
typedef struct ArcCell {
int weight; // 邻接矩阵的元素即为图的边的权值
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
int vexs[MAX_VERTEX_NUM]; // 存放顶点的数组
AdjMatrix arcs; // 邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
}MGraph;
- 优点
- 实现简单直观
- 可以直接查询两点之间是否连通
- 缺点
- 遍历效率低
- 不能存储重边/平行边
- 初始化效率低
- 大图的空间开销大
前向星
int head[maxn]; // 存储起点为Vi的第一条边的位置
struct NODE {
int from;
int to;
int w; // weight
};
NODE edge[maxm];
// 比较函数
// 将所有边的信息读入,按照边的起点排序,
// 若起点相同,对于相同起点的边按终点排序,
// 如果仍有相同,按权值排序
bool cmp(NODE a, NODE b) {
if(a.from==b.from && a.to==b.to) return a.w<b.w;
if(a.from==b.from) return a.to<b.to;
return a.from<b.from;
}
// 读入数据
cin>>n>>m;
for(i=0;i<m;i++) cin>>edge[i].from>>edge[i].to>>edge[i].w;
sort(edge,edge+m,cmp);
memset(head,-1,sizeof(head));
head[edge[0].from]=0;
for(i=1;i<m;i++)
if(edge[i].from != edge[i-1].from) head[edge[i].from]=i;
// 遍历
for(i=1;i<=n;i++) {
for(k=head[i];edge[k].from==i && k<m;k++) {
cout<<edge[k].from<<" "<<edge[k].to<<" "<<edge[k].w;
cout<<endl;
}
}
优点
- 可应对点很多的情况
- 可存储重边
缺点
- 排序会浪费时间
- 无法直接判断两点之间是否连通
邻接表(三种实现)
动态建表
代码引自my_Prim
// 表边结点
typedef struct ArcNode {
int weight;
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
// 表头结点
typedef struct VNode {
int data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
// 图
typedef struct {
int vexnum,arcnum;
AdjList vertices;
}ALGraph;
- 缺点
- 内存释放是个问题
STL/vector模拟链表实现
struct EdgeNode {
int to;
int w;
};
vector<EdgeNode> map[maxn];
EdgeNode e;
cin>>i>>j>>w;
e.to=j; e.w=w;
map[i].push_back(e);
// 遍历
for(i=1;i<=n;i++) {
for(vector<EdgeNode>::iterator k=map[i].begin();k!=map[i].end;k++) {
NODE t=*k;
cout<<i<<' '<<t.to<<' '<<t.w<<endl;
}
}
- 优点
- 代码量少
- 不易犯错
- 内存的申请与释放不需要自己处理
静态建表(链式前向星)
// head数组存储描述点Vi边信息的链的起点在Edges数组的位置
int head[n];
struct EdgeNode {
int to;
int w;
int next;
};
EdgeNode Edges[m];
// 构造链式前向星就是将新加入的结点链在对应链的最开始
// 并修改head数组的对应位置的值
// 信息存储
cin>>i>>j>>w;
Edges[k].to=j;
Edges[k].w=w;
Edges[k].next=head[i]; // 将当前新加入的边的next值
// 设为上条边在Edges中的位置
head[i]=k; // 将当前新加入的边链在之前的边上
// 上两行的操作就和链表中加入一个新结点的操作的意思一样
// 遍历
for(i=1;i<=n;i++) {
for(k=head[i];k!=-1;k=edge[k].next) {
cout<<i<<" "<<edge[k].to<<" "<<edge[k].w<<endl;
}
}
No. | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
head | 10 | 0 | 11 | 6 | 1 | 12 | 7 | 9 |
No. | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
to | 8 | 1 | 3 | 2 | 1 | 3 | 4 | 5 | 7 | 6 | 2 | 7 |
w | 29 | 12 | 11 | 4 | 22 | 17 | 25 | 9 | 7 | 9 | 19 | 4 |
next | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 3 | 4 | 5 | 8 |
链式前向星除了不能直接用起点终点判断是否连通以外,几乎是完美的
References