1. 程式人生 > >資料結構圖之二(最小生成樹--普里姆演算法)

資料結構圖之二(最小生成樹--普里姆演算法)

複製程式碼
  1 #include <iostream>
  2 #include "SeqList.h"
  3 #include <iomanip>
  4 using namespace std;
  5 
  6 #define  INFINITY  65535
  7 
  8 template<class NameType, class DistType>
  9 class Graph
 10 {
 11 private:
 12     SeqList<NameType> Vertices;
 13     DistType **Edges;
14 int nVer, nEdges; 15 16 public: 17 Graph() 18 : Edges(NULL) 19 , nEdges(0) 20 , nVer(0) 21 {} 22 ~Graph() 23 {} 24 25 public: 26 27 istream & operator>>(istream &in) 28 { 29 int v, u, value; 30 int i, j;
31 NameType item; 32 cout << "請輸入頂點的個數: " << endl; 33 in >> nVer; 34 cout << "請輸入頂點的資料資訊: " << endl; 35 for (i = 0; i < nVer; ++i) 36 { 37 in >> item; 38 Vertices.push_back(item); //
儲存全部頂點 39 } 40 /////二維陣列的建立並初始化 41 Edges = new DistType*[nVer]; // DistType *ar[10]; 42 for (i = 0; i < nVer; ++i) 43 { 44 Edges[i] = new DistType[nVer]; 45 for (j = 0; j < nVer; ++j) 46 { 47 Edges[i][j] = 0; 48 } 49 } 50 cout << "請輸入邊的個數: " << endl; 51 in >> nEdges; 52 cout << "請輸入邊的資訊:" << endl; 53 for (i = 0; i < nEdges; ++i) 54 { 55 in >> v >> u >> value; 56 Edges[v][u] = value; 57 Edges[u][v] = value; 58 } 59 return in; 60 } 61 ostream & operator<<(ostream &out) const 62 { 63 int i, j; 64 out << "頂點資訊 " << endl; 65 for (i = 1; i <= nVer; ++i) 66 { 67 out << Vertices[i] << setw(5); 68 } 69 out << endl; 70 out << "矩陣資訊:" << endl; 71 out << setw(10); 72 for (i = 1; i <= nVer; ++i) 73 { 74 out << Vertices[i] << setw(5); 75 } 76 out << endl; 77 for (i = 0; i < nVer; ++i) 78 { 79 out << Vertices[i+1] << setw(5); 80 for (j = 0; j < nVer; ++j) 81 { 82 if (0 == Edges[i][j] && i != j) 83 Edges[i][j] = INFINITY; 84 cout << Edges[i][j] << setw(5); 85 } 86 out << endl; 87 } 88 out << endl; 89 90 return out; 91 } 92 // 圖採用鄰接矩陣儲存 最小生成樹 普里姆演算法 93 void MiniSpanTree() 94 { 95 int min = 0, i = 0, j = 0, k = 0; 96 int* adjvex = new int[nVer]; // 儲存相關頂點下標 97 int* lowcost = new int[nVer]; // 儲存相關頂點間邊的權值 98 lowcost[0] = 0; // 初始化第一個權值為0,即V0已加入生成樹 99 //lowcost的值為0,在這裡就是此下標的頂點已經加入生成樹 100 adjvex[0] = 0; // 初始化第一個頂點下標為0 101 102 for (i = 1; i < nVer; ++i) //迴圈除過下標為0外的全部頂點 103 { 104 lowcost[i] = Edges[0][i]; // 將v0頂點與之有邊的權值存入陣列 105 adjvex[i] = 0; // 並初始化都為v0的下標 106 } 107 108 for (i = 1; i < nVer; ++i) 109 { 110 min = INFINITY; // 初始化最小權值為常數,通常設定為不可能到達的數值 111 k = 0; // 復位 112 113 for (j = 1; j < nVer; ++j) 114 { 115 // 如果兩個頂點之間存在邊有權值,不為0並且小於min 116 if (lowcost[j] != 0 && lowcost[j] < min) 117 { 118 min = lowcost[j]; // 快取最小值 119 k = j; // 將當前最小值的下標快取入k 120 } 121 } 122 cout << "("<< adjvex[k] << "," << k << ")" << endl; //列印當前頂點邊中權值最小的邊 123 lowcost[k] = 0; // 將當前頂點的權值設為0,表示此頂點已經完成任務 124 125 for (j = 1; j < nVer; ++j) // 迴圈所有節點 126 { 127 if (lowcost[j] != 0 && Edges[k][j] < lowcost[j]) 128 { // 若下標為k頂點各邊權值小於此前這些頂點未被加入生成樹權值 129 lowcost[j] = Edges[k][j]; // 用較小者替換 130 adjvex[j] = k; // 將下標為k的頂點存入adjvex 131 } 132 } 133 } 134 135 delete []adjvex; 136 delete []lowcost; 137 adjvex = NULL; 138 lowcost = NULL; 139 } 140 }; 141 142 template<class NameType, class DistType> 143 istream & operator>>(istream &in, Graph<NameType,DistType> &g) 144 { 145 g >> in; 146 return in; 147 } 148 149 template<class NameType, class DistType> 150 ostream & operator<<(ostream &out, const Graph<NameType,DistType> &g) 151 { 152 g << out; 153 return out; 154 } 155 156 void main() 157 { 158 Graph<char, int> myg; 159 cin >> myg; 160 cout << "列印所有輸入資訊:" << endl; 161 cout << myg << endl; 162 cout << "最小生成樹邊資訊如下:" << endl; 163 myg.MiniSpanTree(); 164 cout << endl; 165 }
複製程式碼