我之前没有用过c++,最近在写程序需要使用c++来编写,但是在写的时候遇到这些问题。运行小图时可以得出结果,但是两万多条边的时候,时间特别慢从而导致vs中断。
我用十字链表来存贮一个时序图,时序图有一个开始时间和结束时间,我在之前根据某些条件筛选了一些顶点存在mp集合中,现在我需要按照拓扑排序从下到上遍历这个图,为每一个mp集合中的顶点构建一个可达集合。即每次将下面顶点遍历完的结果 传递给上面的顶点。我用map来存结果,之前遍历map时间很慢,所以我将key放在vector里面遍历,然后再取寻找对应的value。但是效果没有发生改变。
请各位指正!不胜感谢!
map<int,map<int,vector<PAIR>>> result;//用嵌套map来存贮结果
map<int,vector<int>> start;//用一个map来记录图中每个顶点的开始时间
void Graph::MoutSet(Graph G, vector<int> findsort){
Sidetable *p,*q;
map<int,map<int,vector<PAIR>>>::iterator multitr;
map<int,vector<PAIR>>::iterator intertr;
vector<PAIR>::iterator m;
for(int i=0;i<topo.size();i++){//按照从下到上的顺序遍历寻找mout
vector<int>::iterator it;
it = find(mp.begin(), mp.end(), findsort[i]);
if(it!=mp.end()){//如果为mp点
map<int,vector<PAIR>> temp1;//用来存储该顶点的开始时间:(到达顶点,结束时间)
//map<int,vector<PAIR>> tem;
vector<int> sta;//存储开始时间
vector<PAIR> d;
//d.reserve(1000);
p=G._adj[findsort[i]].firstout;//用十字链表结构来存图
while(p!=NULL){//遍历mp点的所有后继节点
sta.emplace_back(p->weight); //把所有开始时间存入vector
it = find(mp.begin(), mp.end(), p->to);
if(it == mp.end()){//后继节点不为mp
q=G._adj[p->to].firstout;
while(q!=NULL){//遍历后继节点的后继节点
for(int i:start[q->to]){//从start开始集合找到满足条件的开始时间,然后在将map中开始时间对应的集合给到当前顶点
if(i>=q->weight+1 && (result[q->to][i].size()!=0)){
d.insert(d.end(),result[q->to][i].begin(),result[q->to][i].end());
}
}
/*if((p->weight+1)<=q->weight){
d.emplace_back(make_pair(q->to,q->weight+1));
for(intertr=result[q->to].begin(); intertr!= result[q->to].end(); intertr++){
if(intertr->first>=q->weight+1){
if(intertr->second.size()==0){
continue;
}
d.insert(d.end(),intertr->second.begin(),intertr->second.end());
}
}
}*/
q=q->taillink;
}
if(d.size()!=0){
temp1.insert(make_pair(p->weight,d));
}
}
else{//如果后继节点为mp
d.emplace_back(make_pair(p->to,p->weight+1));
for(int i:start[p->to]){
if(i>=p->weight+1 && (result[p->to][i].size()!=0)){
d.insert(d.end(),result[p->to][i].begin(),result[p->to][i].end());
}
}
//for(intertr=result[p->to].begin(); intertr!= result[p->to].end(); intertr++){
// //for(int i=0;i<intertr->second.size();i++){
// if(p->weight+1<=intertr->first){
// if(intertr->second.size()==0){
// continue;
// }
// d.insert(d.end(),intertr->second.begin(),intertr->second.end());
// }
// //}
//}
if(d.size()!=0){
temp1.insert(make_pair(p->weight,d));
}
}
//temp1.emplace(pair<int,vector<PAIR>>(p->weight,d));
p=p->taillink;
d.clear();
}
start.emplace(pair<int,vector<int>>(findsort[i],sta));//存储顶点的所有开始时间格式为顶点:{开始时间1,开始时间2.。。。}
result.emplace(pair<int,map<int,vector<PAIR>>>(findsort[i],temp1));
//Mout形式为:
// 顶点1:{开始时间1:[(到达顶点1,结束时间),(到达顶点2,结束时间)],
// 开始时间2:[(到达顶点1,结束时间),(到达顶点2,结束时间)]}
// 顶点2:。。。。
// 顶点3:。。。
}
}
}
传递参数最好能用引用,而不是值,用值类型将发生复制。数据量大会引起性能大幅下降
c++里面的模版虽然很便捷,但是也会延长程序运行时间。
代码里你查找用的vector,容器换其他查找效率高的
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
别听他们胡说,容器函数这些都要学习,当你使用QT以后,你才知道有多重要
DAG的可达性统计只需要把节点编好号用 bitset 就可以了吧,这样时间复杂度大概是 O((n+m)*n/64),点和边在两万以内的数据可以一秒轻松跑出来。
用 map 或者 vector 的时间复杂度至少是 O(n^2),用 vector 仅仅是常数优一些,两万跑起来都很呛。
建议好好学算法,复杂度级别的优化远比常数优化有效。