Prim算法: 采用贪婪算法,通过迭代逐步加入权重最小的边进行构造。
伪代码:
1,初始化U={u0},E为空集; //E是最小生成树的边集合,U是其顶点集合,选定构造最小生成树的出发点u0;
2,重复以下步骤直到U=V;
2.1 以顶点集U和顶点集V-U之间的所有边作为侯选边,从中寻找权值最小的边(u,v)
2.2 令U=U∪{v},E=E∪{(u,v)}
1 #include2 #include >>adjacencyMatrix; //邻接矩阵 35 vector3 #include 4 #include <string> 5 #include 6 7 using namespace std; 8 9 template<class T> 10 struct GraphNode 11 { 12 bool visited; 13 int index; 14 int weight; 15 T vertexName; 16 //自定义优先级:weight小的优先 17 friend bool operator<(GraphNode a, GraphNode b) { 18 return a.weight > b.weight; 19 } 20 }; 21 22 template<class T> 23 class Graph 24 { 25 public: 26 Graph() {} 27 Graph(int * vertexArray, T * nameOfVertex, int numberOfVertex); 28 29 //Prim 30 void Prim(int source); 31 32 private: 33 int vertexNum, arcNum; 34 vector int >graphNodeArray; //顶点信息,只初始化index和vertexName 36 }; 37 38 39 int main() 40 { 41 const int numofVertex = 7; 42 int cost[numofVertex][numofVertex] = { 43 { INT_MAX, 12 , 5 , 11 ,INT_MAX , INT_MAX ,INT_MAX }, 44 { 12, INT_MAX , INT_MAX ,INT_MAX , 33 , INT_MAX ,INT_MAX }, 45 { 5, INT_MAX , INT_MAX , 21 ,INT_MAX , 19 ,INT_MAX }, 46 { 11, INT_MAX , 21 ,INT_MAX , 28 , 8 ,INT_MAX }, 47 { INT_MAX, 33, INT_MAX , 28 ,INT_MAX , INT_MAX , 6 }, 48 { INT_MAX, INT_MAX , 19 , 8 ,INT_MAX , INT_MAX , 16 }, 49 { INT_MAX, INT_MAX , INT_MAX ,INT_MAX , 6 , 16 ,INT_MAX } 50 }; 51 //初始化各顶点 52 string verName[numofVertex] = { "A","B","C","D","E","F","G" }; 53 Graph<string>g(*cost, verName, numofVertex); 54 55 cout << "Prim算法执行结果:" << endl; 56 try { 57 g.Prim(0); 58 } 59 catch (...) { 60 cout << "算法执行失败" << endl; 61 } 62 system("pause"); 63 return 0; 64 } 65 66 template<class T> 67 Graph ::Graph(int * vertexArray, T * nameOfVertex, int numberOfVertex) 68 { 69 vertexNum = numberOfVertex; //顶点数 70 arcNum = 0; 71 GraphNode tempgraphNode; 72 for (int i = 0; i < vertexNum; i++) 73 { 74 tempgraphNode.index = i; 75 tempgraphNode.vertexName = nameOfVertex[i]; 76 graphNodeArray.push_back(tempgraphNode); 77 } 78 //分配所需空间 79 adjacencyMatrix.resize(vertexNum, vector<int>(vertexNum)); 80 for (int i = 0; i < vertexNum; i++) 81 for (int j = 0; j < vertexNum; j++) 82 adjacencyMatrix[i][j] = *(vertexArray + i*vertexNum + j); 83 } 84 85 template<class T> 86 void Graph ::Prim(int source) 87 { 88 int vertextNum = adjacencyMatrix.size(); 89 if (source > vertexNum) 90 throw"位置"; 91 92 vector<int>path(vertexNum); 93 priority_queue >queue; 94 int minIndex; 95 graphNodeArray.resize(vertextNum); //重置足够空间 96 97 for (int i = 0; i < vertextNum; i++) 98 { 99 graphNodeArray[i].visited = false; 100 graphNodeArray[i].weight = INT_MAX; 101 path[i] = source; //记录U 集合双亲关系 102 } 103 graphNodeArray[source].weight = 0; 104 queue.push(graphNodeArray[source]); 105 106 while (!queue.empty()) 107 { 108 GraphNode tempGraphNode = queue.top(); 109 queue.pop(); 110 if (tempGraphNode.visited) 111 continue; 112 tempGraphNode.visited = true; 113 minIndex = tempGraphNode.index; //两个集合之间的权值最小边对应的V-U 中顶点的序号 114 for(int j=0; j ) 115 //两个集合之间的权值最小边对应的V-U中的顶点 的关联边入队 116 if (j != minIndex && !graphNodeArray[j].visited&&adjacencyMatrix[minIndex][j] < graphNodeArray[j].weight) 117 { 118 path[j] = minIndex; 119 graphNodeArray[j].weight = adjacencyMatrix[minIndex][j]; 120 queue.push(graphNodeArray[j]); //边入队,顺便找到其在队中位置 121 } 122 } 123 for (int j = 0; j < vertextNum; j++) 124 { 125 int priorindex = path[j]; 126 if (priorindex != j) 127 cout << graphNodeArray[priorindex].vertexName << "----" << graphNodeArray[j].vertexName << " "; 128 } 129 cout << endl; 130 }
参考前一篇: Kruskal