最小生成樹的PRIM演算法(即時版本)
阿新 • • 發佈:2021-12-05
1 #include <iostream> 2 #include <map> 3 #include <fstream> 4 #include <set> 5 #include <vector> 6 #include <algorithm> 7 8 using namespace std; 9 10 11 class edge{ 12 private: 13 double weight; 14 int v; 15 int w; 16 public:17 edge() = default; // 用 = default 來告訴編譯器要為我們建立預設建構函式 (因為自定義了有引數的建構函式後編譯器就不會建立預設建構函式) 18 edge(const edge&) = default; // !!! 19 edge(edge &e){weight = e.weight;v = e.v; w = e.w;} 20 edge(int _v, int _w, double _weight):v(_v),w(_w),weight(_weight){} 21 double getWeight() const{return weight;} // 為什麼要在後面加const? 因為當edge是一個const例項時,也呼叫這個函式(否則報錯) 22 int either(){return v;} 23 int another(int k) const {if(k == v)return w;else if(k == w)return v;} 24 bool operator<(const edge &ed) const; //should be friend?(不用,因為是自己的成員運算子,所以可以訪問ed的私有成員) 25 bool operator>(const edge &ed){return !operator<(ed);} 26 void show() const {cout << "v: " << v << " w: " << w << " weight: " << weight << endl;} // 沒有const會報錯: passing ‘const edge’ as ‘this’ argument discards qualifiers [-fpermissive]: ed.show(); 27 virtual ~edge(){} 28 }; 29 30 bool edge::operator<(const edge &ed) const{ 31 return weight < ed.weight; 32 } 33 34 class graph{ 35 private: 36 map<int, set<edge>> adj; //這樣直接把edge存放到set中有什麼不妥嗎?是不是應該用智慧指標管理? 37 int V; 38 int E; 39 public: 40 graph(ifstream &in); 41 map<int, set<edge>> getAdj(); 42 void show(); 43 int getv(){return V;} 44 set<int> getAlle(); 45 set<edge> getEdge(int v); 46 ~graph(){} 47 }; 48 49 graph::graph(ifstream &in){ 50 in >> V >> E; 51 int v, w; 52 double weight; 53 while(in >> v >> w >> weight){ 54 //edge temp(v,w,weight); 55 auto v_iter = adj.find(v); 56 if(v_iter != adj.end()){ 57 v_iter->second.emplace(v,w,weight); 58 } 59 else{ 60 set<edge> temps; 61 temps.emplace(v,w,weight); 62 adj[v] = temps; 63 } 64 auto w_iter = adj.find(w); 65 if(w_iter != adj.end()){ 66 w_iter->second.emplace(v,w,weight); 67 } 68 else{ 69 set<edge> temps; 70 temps.emplace(v,w,weight); 71 adj[w] = temps; 72 } 73 } 74 } 75 76 set<int> graph::getAlle(){ 77 set<int> temp; 78 for(auto &item : adj){ 79 temp.insert(item.first); 80 } 81 82 return temp; 83 } 84 85 set<edge> graph::getEdge(int v){ 86 return adj[v]; 87 } 88 89 void graph::show(){ 90 for(auto & item : adj){ 91 cout << "node: " << item.first << endl; 92 for(auto &ed : item.second){ 93 ed.show(); 94 } 95 96 } 97 } 98 99 class primMST 100 { 101 private: 102 graph gp; 103 map<int, bool> marked; 104 map<int, edge> edgeTo; 105 map<int, double> dist; //edgeTo, dist 必須同時更新,因為他們是同一個節點對應的2個值 106 set<int> que; 107 public: 108 primMST() = delete; 109 int getMin(); 110 primMST(graph &_gp); 111 void visit(int v); 112 void show() const; 113 ~primMST(){} 114 }; 115 116 primMST::primMST(graph &_gp):gp(_gp){ 117 int num = gp.getv(); 118 set<int> alle = gp.getAlle(); 119 for(auto &item : alle){ 120 dist[item] = INT32_MAX; 121 } 122 int seed = *(alle.begin()); 123 cout << "seed: " << seed << endl; 124 dist[seed] = 0.0; 125 que.insert(seed); 126 while (que.size()!=0) 127 { 128 visit(getMin()); 129 } 130 131 } 132 133 int primMST::getMin(){ 134 int minior; 135 double weight = INT32_MAX; 136 for_each(que.begin(), que.end(), [&](const int &item){if(this->dist[item] < weight){minior=item;weight = this->dist[item];}}); 137 que.erase(minior); 138 return minior; 139 } 140 141 void primMST::visit(int v){ 142 marked[v]= true; 143 auto allEdge = gp.getEdge(v); 144 for(auto &e : allEdge){ // 因為這裡迭代的每一項e是個const物件,所以下面使用e的類方法必須確保不會改變e的成員變數(所以這些類方法必須在聲名式和定義式後加const(即表示不會修改類內成員)) 145 int w = e.another(v); 146 if(marked.find(w)!=marked.end())continue; 147 if(e.getWeight() < dist[w]){ // dist[w] == edgeTo[w].getWeight() 148 edgeTo[w] = e; // 注意不能用 edgeTo.insert(make_pair(w, e)); 當w重複時就會插入失敗, 不像 edgeTo[w] = e 一樣會更新 149 dist[w] = e.getWeight(); 150 } 151 if(que.find(w)==que.end()){ 152 que.insert(w); 153 } 154 } 155 } 156 157 void primMST::show() const{ 158 cout << "the selected edge: " << endl; 159 for_each(edgeTo.begin(), edgeTo.end(), [](auto &item){cout << "node " << item.first << ": "; item.second.show();}); 160 } 161 162 163 int main(){ 164 edge a(1,2,3); 165 edge b(4,5,6); 166 if(a>b) cout << "a" << endl; 167 168 ifstream file("/home/tanweimin/code/program_practice/ALGORITHM/sort/MST.txt"); 169 graph gp(file); 170 gp.show(); 171 primMST pm(gp); 172 pm.show(); 173 174 return 0; 175 }