Prim算法求最小生成树

Posted guoyujiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prim算法求最小生成树相关的知识,希望对你有一定的参考价值。

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 #include <iostream>
  2 #include <vector>
  3 #include <queue>
  4 #include <string>
  5 #include <climits>
  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<vector<int>>adjacencyMatrix;                    //邻接矩阵
 35     vector<GraphNode<T>>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<T>::Graph(int * vertexArray, T * nameOfVertex, int numberOfVertex)
 68 {
 69     vertexNum = numberOfVertex;                        //顶点数
 70     arcNum = 0;
 71     GraphNode<T> 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<T>::Prim(int source)
 87 {
 88     int vertextNum = adjacencyMatrix.size();
 89     if (source > vertexNum)
 90         throw"位置";
 91 
 92     vector<int>path(vertexNum);
 93     priority_queue<GraphNode<T>>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<T> 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<vertextNum; 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    

以上是关于Prim算法求最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

急!数据结构最小生成树prim算法C语言实现

最小生成树的prim算法 边的权值为啥不能为负值

最小生成树的prim算法 边的权值为啥不能为负值

Prim算法和Kruskal算法求最小生成树

prim和kruscal算法得到的最小生成树是不是一样

急求KRUSKAL算法求最小生成树过程演示