• 第七十七课 最小生成树(Kruskal)


     

    添加kruskal算法:

      1 #ifndef GRAPH_H
      2 #define GRAPH_H
      3 
      4 #include "Object.h"
      5 #include "SharedPointer.h"
      6 #include "Array.h"
      7 #include "DynamicArray.h"
      8 #include "LinkQueue.h"
      9 #include "LinkStack.h"
     10 #include "Sort.h"
     11 
     12 namespace DTLib
     13 {
     14 
     15 template < typename E >
     16 struct Edge : public Object
     17 {
     18     int b;
     19     int e;
     20     E data;
     21 
     22     Edge(int i=-1, int j=-1)
     23     {
     24         b = i;
     25         e = j;
     26     }
     27 
     28     Edge(int i, int j, const E& value)
     29     {
     30         b = i;
     31         e = j;
     32         data = value;
     33     }
     34 
     35     bool operator == (const Edge<E>& obj)
     36     {
     37         return (b == obj.b) && (e == obj.e);  //在这里不关注权值大小
     38     }
     39 
     40     bool operator != (const Edge<E>& obj)
     41     {
     42         return !(*this == obj);
     43     }
     44 
     45     bool operator < (const Edge<E>& obj)
     46     {
     47         return (data < obj.data);
     48     }
     49 
     50     bool operator > (const Edge<E>& obj)
     51     {
     52         return (data > obj.data);
     53     }
     54 };
     55 
     56 template < typename V, typename E >
     57 class Graph : public Object
     58 {
     59 protected:
     60     template < typename T >
     61     DynamicArray<T>* toArray(LinkQueue<T>& queue)
     62     {
     63         DynamicArray<T>* ret = new DynamicArray<T>(queue.length());
     64 
     65         if( ret != NULL )
     66         {
     67             for(int i=0; i<ret->length(); i++, queue.remove())
     68             {
     69                 ret->set(i, queue.front());
     70             }
     71         }
     72         else
     73         {
     74             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret object...");
     75         }
     76 
     77         return ret;
     78     }
     79 
     80     SharedPointer< Array<Edge<E> > > getUndirectedEdges()
     81     {
     82         DynamicArray<Edge<E>>* ret = NULL;
     83 
     84         if( asUndirected() )
     85         {
     86             LinkQueue<Edge<E>> queue;
     87 
     88             for(int i=0; i<vCount(); i++)
     89             {
     90                 for(int j=i; j<vCount(); j++)
     91                 {
     92                     if( isAdjacent(i, j) )
     93                     {
     94                         queue.add(Edge<E>(i, j, getEdge(i, j)));
     95                     }
     96                 }
     97             }
     98 
     99             ret = toArray(queue);
    100         }
    101         else
    102         {
    103             THROW_EXCEPTION(InvalidOperationException, "This function is for undirected graph only...");
    104         }
    105 
    106         return ret;
    107     }
    108 
    109     int find(Array<int>& p, int v)
    110     {
    111         while( p[v] != -1)
    112         {
    113             v = p[v];
    114         }
    115 
    116         return v;
    117     }
    118 public:
    119     virtual V getVertex(int i) = 0;
    120     virtual bool getVertex(int i, V& value) = 0;
    121     virtual bool setVertex(int i, const V& value) = 0;
    122     virtual SharedPointer< Array<int> > getAdjacent(int i) = 0;
    123     virtual bool isAdjacent(int i, int j) = 0;
    124     virtual E getEdge(int i, int j) = 0;
    125     virtual bool getEdge(int i, int j, E& value) = 0;
    126     virtual bool setEdge(int i, int j, const E& value) = 0;
    127     virtual bool removeEdge(int i, int j) = 0;
    128     virtual int vCount() = 0;
    129     virtual int eCount() = 0;
    130     virtual int OD(int i) = 0;
    131     virtual int ID(int i) = 0;
    132 
    133     virtual int TD(int i)
    134     {
    135         return ID(i) + OD(i);
    136     }
    137 
    138     bool asUndirected()
    139     {
    140         bool ret = true;
    141 
    142         for(int i=0; i<vCount(); i++)
    143         {
    144             for(int j=0; j<vCount(); j++)
    145             {
    146                 if( isAdjacent(i, j) )
    147                 {
    148                     ret = ret && isAdjacent(j, i) && (getEdge(i, j) == getEdge(j, i));
    149                 }
    150             }
    151         }
    152 
    153         return ret;
    154     }
    155 
    156     SharedPointer< Array< Edge<E > > > prim(const E& LIMIT, const bool MINIUM = true) //参数为理论上的最大权值
    157     {
    158         LinkQueue< Edge<E> > ret;
    159 
    160         if( asUndirected() )
    161         {
    162             DynamicArray<int> adjVex(vCount());
    163             DynamicArray<bool> mark(vCount());
    164             DynamicArray<E> cost(vCount());
    165             SharedPointer< Array<int> > aj = NULL;
    166             bool end = false;
    167             int v = 0;
    168 
    169             for(int i=0; i<vCount(); i++)
    170             {
    171                 adjVex[i] = -1;
    172                 mark[i] = false;
    173                 cost[i] = LIMIT;
    174             }
    175 
    176             mark[v] = true;
    177 
    178             aj = getAdjacent(v);
    179 
    180             for(int j=0; j<aj->length(); j++)
    181             {
    182                 cost[(*aj)[j]] = getEdge(v, (*aj)[j]);
    183                 adjVex[(*aj)[j]] = v;
    184             }
    185 
    186             for(int i=0; (i<vCount()) && !end; i++)
    187             {
    188                 E m = LIMIT;
    189                 int k = -1;
    190 
    191                 for(int j=0; j<vCount(); j++)
    192                 {
    193                     if( !mark[j] && (MINIUM ? (cost[j] < m) : (cost[j] > m)))
    194                     {
    195                         m = cost[j];
    196                         k = j;
    197                     }
    198                 }
    199 
    200                 end = (k == -1);
    201 
    202                 if( !end )
    203                 {
    204                     ret.add(Edge<E>(adjVex[k], k, getEdge(adjVex[k], k)));
    205 
    206                     mark[k] = true;
    207 
    208                     aj = getAdjacent(k);
    209 
    210                     for(int j=0; j<aj->length(); j++)
    211                     {
    212                         if( !mark[(*aj)[j]] && (MINIUM ? (getEdge(k, (*aj)[j]) < cost[(*aj)[j]]) : (getEdge(k, (*aj)[j]) > cost[(*aj)[j]])) )
    213                         {
    214                             cost[(*aj)[j]] = getEdge(k, (*aj)[j]);
    215                             adjVex[(*aj)[j]] = k;
    216                         }
    217                     }
    218                 }
    219             }
    220         }
    221         else
    222         {
    223             THROW_EXCEPTION(InvalidOperationException, "Prim operator is for undirected graph only...");
    224         }
    225 
    226         if( ret.length() != (vCount() - 1) )
    227         {
    228             THROW_EXCEPTION(InvalidOperationException, "No enough edge for prim operation...");
    229         }
    230 
    231         return toArray(ret);
    232     }
    233 
    234     SharedPointer< Array<Edge<E> > > kruskal(const bool MINMUM = true)
    235     {
    236         LinkQueue< Edge<E> > ret;
    237 
    238         SharedPointer< Array< Edge<E> > > edges = getUndirectedEdges();
    239 
    240         DynamicArray<int> p(vCount()); //前驱标记数组
    241 
    242         for(int i=0; i<p.length(); i++)
    243         {
    244             p[i] = -1;
    245         }
    246 
    247         Sort::Shell(*edges, MINMUM);
    248 
    249         for(int i=0; (i<edges->length()) && (ret.length() < (vCount() - 1)); i++)
    250         {
    251             int b = find(p, (*edges)[i].b);
    252             int e = find(p, (*edges)[i].e);
    253 
    254             if( b != e )
    255             {
    256                 p[e] = b;
    257 
    258                 ret.add((*edges)[i]);
    259             }
    260         }
    261 
    262         if( ret.length() != (vCount() - 1) )
    263         {
    264             THROW_EXCEPTION(InvalidOperationException, "No enough edges for Kruskal operation...");
    265         }
    266 
    267         return toArray(ret);
    268     }
    269 
    270     SharedPointer< Array<int> > BFS(int i)
    271     {
    272         DynamicArray<int>* ret = NULL;
    273 
    274         if( (0 <= i) && (i < vCount()) )
    275         {
    276             LinkQueue<int> q;
    277             LinkQueue<int> r;
    278             DynamicArray<bool> visited(vCount());
    279 
    280             for(int i=0; i<visited.length(); i++)
    281             {
    282                 visited[i] = false;
    283             }
    284 
    285             q.add(i);
    286 
    287             while( q.length() > 0 )
    288             {
    289                 int v = q.front();
    290 
    291                 q.remove();
    292 
    293                 if( !visited[v] )
    294                 {
    295                     SharedPointer< Array<int> > aj = getAdjacent(v);
    296 
    297                     for(int j=0; j<aj->length(); j++)
    298                     {
    299                         q.add((*aj)[j]);
    300                     }
    301 
    302                     r.add(v);
    303 
    304                     visited[v] = true;
    305                 }
    306             }
    307 
    308             ret = toArray(r);
    309         }
    310         else
    311         {
    312             THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
    313         }
    314 
    315         return ret;
    316     }
    317 
    318     SharedPointer< Array<int> > DFS(int i)
    319     {
    320         DynamicArray<int>* ret = NULL;
    321 
    322         if( (0 <= i) && (i < vCount()) )
    323         {
    324             LinkStack<int> s;
    325             LinkQueue<int> r;
    326             DynamicArray<bool> visited(vCount());
    327 
    328             for(int j=0; j<visited.length(); j++)
    329             {
    330                 visited[j] = false;
    331             }
    332 
    333             s.push(i);
    334 
    335             while( s.size() > 0 )
    336             {
    337                 int v = s.top();
    338 
    339                 s.pop();
    340 
    341                 if( !visited[v] )
    342                 {
    343                     SharedPointer< Array<int> > aj = getAdjacent(v);
    344 
    345                     for(int j=aj->length() - 1; j>=0; j--)
    346                     {
    347                         s.push((*aj)[j]);
    348                     }
    349 
    350                     r.add(v);
    351 
    352                     visited[v] = true;
    353                 }
    354             }
    355 
    356             ret = toArray(r);
    357         }
    358         else
    359         {
    360             THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
    361         }
    362 
    363         return ret;
    364     }
    365 
    366 };
    367 
    368 }
    369 
    370 #endif // GRAPH_H

    测试程序如下:

      1 #include <iostream>
      2 #include "MatrixGraph.h"
      3 #include "ListGraph.h"
      4 
      5 using namespace std;
      6 using namespace DTLib;
      7 
      8 template< typename V, typename E >
      9 Graph<V, E>& GraphEasy()
     10 {
     11     static MatrixGraph<4, V, E> g;
     12 
     13     g.setEdge(0, 1, 1);
     14     g.setEdge(1, 0, 1);
     15 
     16     g.setEdge(0, 2, 3);
     17     g.setEdge(2, 0, 3);
     18 
     19     g.setEdge(1, 2, 1);
     20     g.setEdge(2, 1, 1);
     21 
     22     g.setEdge(1, 3, 4);
     23     g.setEdge(3, 1, 4);
     24 
     25     g.setEdge(2, 3, 1);
     26     g.setEdge(3, 2, 1);
     27 
     28     return g;
     29 }
     30 
     31 template< typename V, typename E >
     32 Graph<V, E>& GraphComplex()
     33 {
     34     static ListGraph<V, E> g(9);
     35 
     36     g.setEdge(0, 1, 10);
     37     g.setEdge(1, 0, 10);
     38 
     39     g.setEdge(0, 5, 11);
     40     g.setEdge(5, 0, 11);
     41 
     42     g.setEdge(1, 2, 18);
     43     g.setEdge(2, 1, 18);
     44 
     45     g.setEdge(1, 8, 12);
     46     g.setEdge(8, 1, 12);
     47 
     48     g.setEdge(1, 6, 16);
     49     g.setEdge(6, 1, 16);
     50 
     51     g.setEdge(2, 3, 22);
     52     g.setEdge(3, 2, 22);
     53 
     54     g.setEdge(2, 8, 8);
     55     g.setEdge(8, 2, 8);
     56 
     57     g.setEdge(3, 8, 21);
     58     g.setEdge(8, 3, 21);
     59 
     60     g.setEdge(3, 6, 24);
     61     g.setEdge(6, 3, 24);
     62 
     63     g.setEdge(3, 7, 16);
     64     g.setEdge(7, 3, 16);
     65 
     66     g.setEdge(3, 4, 20);
     67     g.setEdge(4, 3, 20);
     68 
     69     g.setEdge(4, 5, 26);
     70     g.setEdge(5, 4, 26);
     71 
     72     g.setEdge(4, 7, 7);
     73     g.setEdge(7, 4, 7);
     74 
     75     g.setEdge(5, 6, 17);
     76     g.setEdge(6, 5, 17);
     77 
     78     g.setEdge(6, 7, 19);
     79     g.setEdge(7, 6, 19);
     80 
     81     return g;
     82 }
     83 
     84 int main()
     85 {
     86     Graph<int, int>& g = GraphComplex<int, int>();
     87 
     88     SharedPointer< Array< Edge<int> > > sa = g.kruskal();
     89 
     90     int w = 0;
     91 
     92     for(int i=0; i<sa->length(); i++)
     93     {
     94         w += (*sa)[i].data;
     95         cout << (*sa)[i].b << " " << (*sa)[i].e << " " << (*sa)[i].data << endl;
     96     }
     97 
     98     cout << "Weight: " << w << endl;
     99 
    100     return 0;
    101 }

    结果如下:

    小结:

  • 相关阅读:
    【译】第33节---种子数据
    python文件的读写
    python-----实现数据库安装和连接操作
    学习进度(第三周)
    解 idea(.IntelliJIdea2019.3)双击打不开的原因
    python爬虫------处理cookie的相关请求
    安装retrying模块出现 (Retry(total=4, connect=None, read=None, redirect=None, status=None))
    java----统计疫情可视化展示--echarts(三)
    java----统计疫情可视化展示--echarts(二)
    java----统计疫情可视化展示--echarts
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9734223.html
Copyright © 2020-2023  润新知