图的各种算法实现

  1. #ifndef _ALGORITHM_H_2008_
  2. #define _ALGORITHM_H_2008_
  3. #include "Graph.h"
  4. //深度优先遍历算法
  5. template<bool pre,class FirstArg,class ResultType>
  6. void DFS(Graph& graph,Graph::size_t start,const pointer_to_unary_function<FirstArg,ResultType>& _func){
  7.     graph.visit(graph[start]);
  8.     Vertex& ve=graph[start];
  9.     if(pre && &_func!=NULL){
  10.         _func(ve);
  11.     }
  12.     for(Edge* e=ve.getFirstEdge();e!=NULL;e=ve.getNextEdge(*e)){
  13.         if(!graph.isVisited(e->getTarget().getIndex())){
  14.             DFS<pre>(graph,e->getTarget().getIndex(),_func);
  15.             graph.visit(*e);
  16.         }
  17.     }
  18.     if(!pre&& &_func!=NULL)
  19.         _func(ve);
  20. }
  21. //广度优先遍历算法
  22. template<class FirstArg,class ResultType>
  23. void BFS(Graph& graph,Graph::size_t start,const pointer_to_unary_function<FirstArg,ResultType>& _func){
  24.     assert(start<graph.getVerticesNum());
  25.     graph.clearState();
  26.     typedef Graph::Reference reference;
  27.     queue<int> vertexQueue;
  28.     graph.visit(graph[start]);
  29.     if(&_func!=NULL)
  30.         _func(graph[start]);
  31.     vertexQueue.push(start);
  32.     while(!vertexQueue.empty()){
  33.         reference ve=graph[vertexQueue.front()];
  34.         vertexQueue.pop();
  35.         for(Edge* e=ve.getFirstEdge();e!=NULL;e=ve.getNextEdge(*e)){
  36.             Graph::size_t index=e->getTarget().getIndex();
  37.             if(!graph.isVisited(index)){
  38.                 graph.visit(graph[index]);
  39.                 graph.visit(*e);
  40.                 if(&_func!=NULL)
  41.                     _func(graph[index]);
  42.                 vertexQueue.push(index);
  43.             }
  44.         }
  45.     }
  46.     graph.clearState();
  47. }
  48. //拓扑顺序遍历
  49. template<class FirstArg,class ResultType>
  50. bool Toplogic(Graph& graph,const pointer_to_unary_function<FirstArg,ResultType> _func){
  51.     int* inDegree=new int[graph.getVerticesNum()];
  52.     queue<int> veQueue;
  53.     for(int i=0;i<graph.getVerticesNum();i++){
  54.         inDegree[i]=graph[i].getInDegree();
  55.         if(inDegree[i]==0)
  56.             veQueue.push(i);
  57.     }
  58.     int sum=0;
  59.     while(!veQueue.empty()){
  60.         int v=veQueue.front();
  61.         veQueue.pop();
  62.         graph.visit(graph[v]);
  63.         if(&_func!=NULL)
  64.             _func(graph[v]);
  65.         sum++;
  66.         for(Edge* e=graph[v].getFirstEdge();e!=NULL;e=graph[v].getNextEdge(*e)){
  67.             int i=e->getTarget().getIndex();
  68.             inDegree[i]--;
  69.             if(inDegree[i]==0)
  70.                 veQueue.push(i);
  71.         }
  72.     }
  73.     if(sum!=graph.getVerticesNum()){
  74.         printf("图中存在环");
  75.         return false;
  76.     }
  77.     return true;
  78. }
  79. void popStack(Graph& graph,vector<int>& vStack,int u,vector<vector<Vertex*>>& block){
  80.     vector<Vertex*> newBlock;
  81.     while(!vStack.empty()){
  82.         int index=vStack.back();
  83.         newBlock.push_back(&graph[index]);
  84.         vStack.pop_back();
  85.         if(index==u)
  86.             break;
  87.     }
  88.     block.push_back(newBlock);
  89. }
  90. //寻找图的割点和最大块
  91. //low[u]=|__dfn[u]  u was firstly visited
  92. //       |__min(low[u],dfn[w])  uw was edge which w has been visited
  93. //       |__min(low[u],low[s])  all of the edges of u's son has been checked
  94. //1  if a root has not only one child then this root is a cutvertex
  95. //2  if low[u]>=low[father[u]] then u is a cutvertex
  96. void FindCutVertexAndBlock(Graph& graph,vector<Vertex*>& cutVertex,vector<vector<Vertex*>>& block){
  97.     graph.clearState();
  98.     int vertexSize=graph.getVerticesNum();
  99.     int* dfn=new int[vertexSize];
  100.     memset(dfn,0,vertexSize*sizeof(int));
  101.     int* low=new int[vertexSize];
  102.     memset(low,0,vertexSize*sizeof(int));
  103.     int* father=new int[vertexSize];
  104.     memset(father,0,vertexSize*sizeof(int));
  105.     vector<int> vertexStack;
  106.     int u=0;    //初始访问节点
  107.     bool reflashStack=true;
  108.     Edge* e=NULL;
  109.     int i=1;
  110.     while(true){
  111.         if(reflashStack){
  112.             dfn[u]=i;
  113.             low[u]=i;
  114.             vertexStack.push_back(u);
  115.             e=graph[u].getFirstEdge();
  116.             i++;
  117.         }
  118.         else
  119.             reflashStack=true;
  120.         for(;e!=NULL;e=graph[u].getNextEdge(*e))
  121.             if(!graph.isVisited(*e))
  122.                 break;
  123.         if(e!=NULL)       //有未使用的边
  124.         {
  125.             graph.visit(*e);
  126.             int v=e->getTarget().getIndex();
  127.             if(dfn[v]==0){  //v是子节点,访问
  128.                 father[v]=u;  //u是v的父节点
  129.                 u=v;
  130.             }
  131.             else{            //u-v是一条指向已经被访问过的节点的边
  132.                 low[u]=min(low[u],dfn[v]);  //如果v在u之前被访问过,则low[u]指向v
  133.                 reflashStack=false;         //u节点不重新入栈
  134.             }
  135.             continue;
  136.         }
  137.         else{            //u的所有子节点都被访问
  138.             if(dfn[father[u]]==1)//u的父节点是初始节点,
  139.             {
  140.                 popStack(graph,vertexStack,father[u],block);
  141.                 e=graph[father[u]].getFirstEdge();
  142.                 for(;e!=NULL;e=graph[father[u]].getNextEdge(*e))
  143.                     if(!graph.isVisited(*e))
  144.                         break;
  145.                 if(e!=NULL){                        //根节点还有未使用的边,根是割点
  146.                     u=father[u];
  147.                     cutVertex.push_back(&graph[u]);
  148.                     reflashStack=false;            
  149.                     continue;
  150.                 }
  151.                 else{
  152.                     int * first=find(dfn,dfn+graph.getVerticesNum(),0);
  153.                     u=first-dfn;
  154.                     if(u>=graph.getVerticesNum() || u<0)
  155.                         break;
  156.                     continue;
  157.                 }
  158.             }
  159.             else{
  160.                 reflashStack=false;
  161.                 if(low[u]<dfn[father[u]]){            //u节点的指向节点比u的父节点小,更新父节点指向
  162.                     low[father[u]]=min(low[father[u]],low[u]);                  
  163.                     u=father[u];                        //u遍历完毕,回溯
  164.                 }
  165.                 else{                                //u的子节点S没有到u的祖先节点的后向边,u是割点,u以上的节点形成块
  166.                     u=father[u];
  167.                     popStack(graph,vertexStack,u,block);
  168.                     cutVertex.push_back(&graph[u]);
  169.                 }
  170.             }
  171.         }
  172.     }
  173.     graph.clearState();
  174. }
  175. //寻找图的最大连通子图
  176. int FindGreatestConnectedSubGraph(Graph& graph,vector<vector<Vertex*>>& subGraph){
  177.     graph.clearState();
  178.     int vertexSize=graph.getVerticesNum();
  179.     int* dfn=new int[vertexSize];
  180.     memset(dfn,0,vertexSize*sizeof(int));
  181.     int* low=new int[vertexSize];
  182.     memset(low,0,vertexSize*sizeof(int));
  183.     int* father=new int[vertexSize];
  184.     memset(father,-1,vertexSize*sizeof(int));
  185.     vector<int> vertexStack;
  186.     int u=0;    //初始访问节点
  187.     bool reflashStack=true;
  188.     Edge* e=NULL;
  189.     int i=1;
  190.     int maxIndex=-1;
  191.     int maxSize=0;
  192.     while(true){
  193.         if(reflashStack){
  194.             dfn[u]=i;
  195.             low[u]=i;
  196.             vertexStack.push_back(u);
  197.             e=graph[u].getFirstEdge();
  198.             i++;
  199.         }
  200.         else
  201.             reflashStack=true;
  202.         for(;e!=NULL;e=graph[u].getNextEdge(*e))
  203.             if(!graph.isVisited(*e))
  204.                 break;
  205.         if(e!=NULL)       //有未使用的边
  206.         {
  207.             graph.visit(*e);
  208.             int v=e->getTarget().getIndex();
  209.             if(dfn[v]==0){         //未访问的子节点
  210.                 father[v]=u;
  211.                 u=v;
  212.                 continue;
  213.             }
  214.             else if(dfn[v]<dfn[u] && find(vertexStack.begin(),vertexStack.end(),v)!=vertexStack.end()){
  215.                 low[u]=min(low[u],low[v]);
  216.                 reflashStack=false;
  217.             }
  218.             else
  219.                 reflashStack=false;
  220.         }
  221.         else{
  222.             if(low[u]==dfn[u]){    //极大连通子图
  223.                 popStack(graph,vertexStack,u,subGraph);
  224.                 if(subGraph.back().size()>maxSize){
  225.                     maxSize=subGraph.back().size();
  226.                     maxIndex=subGraph.size()-1;
  227.                 }
  228.             }
  229.             if(father[u]>=0){
  230.                 low[father[u]]=min(low[father[u]],low[u]);
  231.                 u=father[u];
  232.                 reflashStack=false;
  233.             }
  234.             else{
  235.                 int* first=find(dfn,dfn+graph.getVerticesNum(),0);
  236.                 u=first-dfn;
  237.                 if(u>=graph.getVerticesNum() || u<0)
  238.                     break;
  239.             }
  240.         }
  241.     }
  242.     return maxSize;
  243. }
  244. #endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值