vector动态数组邻接表--功能更强大的邻接表
来源:互联网 发布:收款收据打印软件 编辑:程序博客网 时间:2024/06/04 22:33
某些时候邻接表可能有局限性。
有一种Vector动态数组+结构体的有效替代法。
它的边遍历顺序可以自己定义:
若正序遍历,遍历顺序与邻接表相反;
若反序遍历,遍历顺序与邻接表相同。
还可以对每个vector进行排序后遍历。
在某些需要遍历某个特殊点编号时,可以sort()后二分查找与这个点最接近的点编号,优先遍历,从而达到增大遍历几率,减少时间的作用。
对于这个点是n号节点,则可以sort()后直接从后往前遍历,某些时候可以卡过毒瘤出题人的数据。。。
这些都是邻接表所没有的功能。
例如:保存有向图:
给定n个点m条边,用三个数表示从a点到b点有一条距离为c的边。
struct data{ vector <int> to; vector <int> dis; int m; //m用于存储边数,方便遍历 /*data()//用于提速,但保留的空间也算入总空间 { to.reserve(70);//对于大部分图已经够用了 dis.reserve(70); }*/}num[10000]; //num[i]表示编号为i的点for (a=1;a<=n;a++){ num[a].to.push_back(0); num[a].dis.push_back(0);}//由于个人比较习惯从1号开始,所以填掉了0号位for (a=1;a<=m;a++){ scanf("%d%d%d",&b,&c,&d);//表示从b到c有一条长为d的边 num[b].to.push_back(c); num[b].dis.push_back(d); num[b].m++;//计数 /* num[c].to.push_back(b);//无向图 num[c].dis.push_back(d); num[c].m++; */}
这种方法中,注意to与dis是一一对应关系。
比如说,遍历全图,时间复杂度为O(n+m):
void dfs(int x){ vis[x]=1; int i; for (i=1;i<=num[x].m;++i) if (!vis[ num[x].to[a] ]) dfs(num[x].to[a]);}
若是初学,看得晕,可以将点取出来,便于理解:
v=num[a].to[b];//到达的点u=num[a].dis[b];//边长
下面发两个代码来验证使用方法:
SPFA-Vector:
#include<iostream>#include<cstdio>#include<queue>#include<vector>using namespace std;int l,m,n,s,q,k;int v,u;int dis[1001],team[1001];bool exist[2010];struct sr{ vector <int> to; vector <int> length; int mem;}num[1001];int head,tail;int main(){ int a,b,c,d,e; cin>>n>>m; for (a=1;a<=m;a++) { dis[a]=999999; num[a].to.push_back(999999); num[a].length.push_back(999999); } for (a=1;a<=m;a++) { scanf("%d%d%d",&b,&c,&d); num[b].to.push_back(c); num[b].mem++; num[b].length.push_back(d); num[c].to.push_back(b); num[c].mem++; num[c].length.push_back(d); } team[1]=1; head=0; tail=1; exist[1]=true; dis[1]=0; do { head++; k=team[head]; exist[k]=0; for (a=1;a<=num[k].mem;a++) { v=num[k].to[a]; if (dis[v] > dis[k] + num[k].length[a] ) { dis[v] = dis[k] + num[k].length[a]; if (! exist[v] ) { tail++; team[tail]=num[k].to[a]; exist[ num[k].to[a] ]=1; } } } }while (head<tail); cout<<dis[n]; return 0;}
Dijkstra堆优化-Vector:
#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<cstring>using namespace std;int dis[10010];bool exist[10010];struct cmp{ bool operator()(int a,int b) { return dis[a]>dis[b]; }};struct data{ vector <int> to; vector <int> dis; int m;}num[10010];int l,m,n,s,q,u,v;priority_queue<int,vector<int>,cmp> Q;int main(){ int a,b,c,d,e; cin>>n>>m; for (a=1;a<=n;a++) { num[a].to.push_back(0); num[a].dis.push_back(0); dis[a]=9999999; exist[a]=0; } for (a=1;a<=m;a++) { scanf("%d%d%d",&b,&c,&d); num[b].to.push_back(c); num[b].dis.push_back(d); num[b].m++; num[c].to.push_back(b); num[c].dis.push_back(d); num[c].m++; } dis[1]=0; exist[1]=1; Q.push(1); while (!Q.empty()) { u=Q.top(); Q.pop(); exist[u]=1; l=num[u].m; for (a=1;a<=l;a++) { v=num[u].to[a]; if (!exist[v] && dis[u]+num[u].dis[a]<dis[v]) { dis[v]=dis[u]+num[u].dis[a]; Q.push(v); } } } cout<<dis[n]; return 0;}
有时候会出现多组数据,那么可以写一个初始化函数:
void clr(){ int a; for (a=1;a<=n;a++) { num[a].to.clear(); num[a].dis.clear(); num[a].m=0; }}
时间复杂度为O(n)。
动态数组邻接表法建表容易,理解简单,比普通邻接表略省空间,由于vector的局限性导会耗费更多时间,但可以通过reserve()函数得到有效解决。
阅读全文
2 0
- vector动态数组邻接表--功能更强大的邻接表
- vector 邻接表的建立
- vector 实现邻接表
- 邻接表的数组实现
- 邻接表的数组实现
- 邻接表的数组实现
- 邻接表-数组的实现
- 不用vector的邻接表的写法
- 邻接表的vector表示方法
- 使用vector构造带权图的邻接表
- 【邻接表】数组模拟邻接表
- 数组邻接表
- 数组模拟邻接表
- 数组实现邻接表
- 数组邻接表
- 数组表示邻接表
- 邻接表数组实现
- 邻接表-动态和静态的学习
- 2017.9.28 降雨量 思考记录
- java之重写与重载
- [Unity框架]PureMVC基础
- 链表中环的入口点
- bug解决-内核C库写保护(FORTIFY: write: prevented read past end of buffer)
- vector动态数组邻接表--功能更强大的邻接表
- CXF生成客户端代码并打包成jar文件
- 51nod 1616 最小集合
- 嵌入式 GCC或者G++编译优化选项
- 稳定排序和不稳定排序
- 工作的轻重缓急
- .nte连接数据库常见问题,Unknown column '张三' in 'where clause'
- DSP28335笔记--SCI篇
- 误差反向传播算法浅解