运用三种方式来实现图的存储,以适应不同的情况。
参考:ACM-ICPC程序设计系列——图论及应用
方式1:邻接矩阵
邻接矩阵是表示图的数据结构中最简单也是最常用的一种。
实现:二维数组Map[MAXN][MAXN],Map[i][j]表示点i到点j的距离。
初始化:Map[i][i] = 0,Map[i][j] = INF(i!=j),读入数据Map[i][j] = w。
时间复杂度:初始化O(n^2),建图需要O(m),总时间复杂度O(n^2)。
优缺点:简单直观,可直接查询点i和点j之间是否有边;遍历效率低,不
能存储重编;初始化效率低;大图开销大,适合存储点少的稠密图。
方式2:前向星
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 100; const int MAXM = 100; int head[MAXN];//存储起点为i的第一条边的位置 struct node { int from;//起点 int to;//终点 int w;//权值 }; 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; } int main() { int n,m; cin >> n >> m; for(int 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(int i = 1; i < m; i++)//确定起点为i的第一条边位置 { if(edge[i].from != edge[i-1].from) head[edge[i].from] = i; } for(int i = 1; i <= n; i++)//遍历图 { //k为第i个结点边的起始位置 for(int k = head[i]; edge[k].from == i && k < m; k++) { cout << edge[k].from << ' ' << edge[k].to << ' ' << edge[k].w << endl; } } return 0; } /* 7 8 1 1 1 1 3 1 1 3 2 3 5 1 3 6 1 4 6 1 2 4 1 1 2 1 */
方式3:邻接表——动态建表
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 100; struct EdgeNode<span style="white-space:pre"> </span>//邻接表节点 { int to;<span style="white-space:pre"> </span>//终点 int w;<span style="white-space:pre"> </span>//权值 EdgeNode *next;<span style="white-space:pre"> </span>//指向下一条边的指针 }; struct VNode<span style="white-space:pre"> </span>//起点表节点 { int from;<span style="white-space:pre"> </span>//起点 EdgeNode *first;<span style="white-space:pre"> </span>//邻接表头指针 }; VNode Adjlist[MAXN];<span style="white-space:pre"> </span>//整个图的邻接表 int main() { int n,m,x,y,w; cin >> n >> m; for(int i = 0; i < m; i++)//读入图 { cin >> x >> y >> w; EdgeNode *p = new EdgeNode(); p->to = y; p->w = w; p->next = Adjlist[x].first; Adjlist[x].first = p; } cout << endl; for(int i = 1; i <= n; i++)//遍历图 { for(EdgeNode *k = Adjlist[i].first; k != NULL; k = k->next) cout << i << ' ' << k->to << ' ' << k->w << endl; } return 0; }
方式4:邻接表——vector模拟链表实现
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 100; const int MAXM = 100; struct EdgeNode<span style="white-space:pre"> </span>//边表节点类型 { int to;<span style="white-space:pre"> </span>//终点 int w;<span style="white-space:pre"> </span>//权值 }; vector<EdgeNode> Map[MAXN]; int main() { EdgeNode e; int n,m,x,y,w; cin >> n >> m; for(int i = 0; i < m; i++)<span style="white-space:pre"> </span>//读入图 { cin >> x >> y >> w; e.to = y; e.w = w; Map[x].push_back(e); } cout << endl; for(int i = 1; i <= n; i++)<span style="white-space:pre"> </span>//遍历图 { for(vector <EdgeNode>::iterator k = Map[i].begin(); k!=Map[i].end(); k++) { EdgeNode t = *k; cout << i << ' ' << t.to << ' ' << t.w << endl; } } return 0; }
方式5:邻接表——链式前向星★
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 100; const int MAXM = 100; int head[MAXN]; struct EdgeNode { int to; int w; int next; }; EdgeNode Edges[MAXM]; int main() { int n,m,x,y,w; cin >> n >> m; memset(head,-1,sizeof(head)); for(int i = 0; i < m; i++) { cin >> x >> y >> w; Edges[i].to = y; Edges[i].w = w; Edges[i].next = head[x]; head[x] = i; } cout << endl; for(int i = 1; i <= n; i++) { for(int k = head[i]; k!= -1; k = Edges[k].next) cout << i << ' ' << Edges[k].to << ' ' << Edges[k].w << endl; } return 0; }
时间: 2024-12-10 11:49:14