您的位置:首页 > 其它

最小生成树之Prim算法

2014-07-28 10:59 274 查看
Prim算法的流程为,首先从任意一个节点出发,逐渐生成,直至该树覆盖了所有的V中的节点。

如下图:



图中的黑色的边即是最小生成树中的边。

实现Prim算法的关键是,如何选择一条 “权值较小并且对于已有生成树中的点集合S来说是安全的边”,此处的安全指的是:

加入该边e之后,S仍然是一个树。

于是:对于图 G = (V, E) Prim的执行步骤大致为:

1
  从 任意节点s 开始,因此将原来的顶点集合分为两部分: S = {s},  T = V- S =  V  - {s},

2   计算T中的节点到S中的节点的距离,即对于T中的节点v而言, d(v) = min{(u,v), u 属于S };

3   选出所有的(2)中的计算的最短的权,加入到S中,并且更新S与T中的点的集合。

4   重复2,3步,直至所有的节点都在S中,T为空。

执行完毕。

上述的步骤可由下面的简单的图解来解释:




因此最终的结果是17.

上述最重要的便是记录不在S中的节点到S中的最短的距离。这显然可以使用优先队列(堆)来实现,但是在选中该点之后,需要更新它的邻居节点的距离信息,即会减小队列中的key值,这是优先队列没有实现的,于是我自行实现了一个最小堆,并且实现了Prim算法,代码如下:

//Heap

#ifndef _HEAP_H
#define _HEAP_H

#include
using namespace std;

typedef pair  Elem;

struct cmp:public binary_function
{
bool operator()(const Elem &lhs, const Elem &rhs)
{
return lhs.second > rhs.second;
}
};

class Heap
{
private:
vector content;

public:
Heap(){}
template
Heap(InputIterator beg, InputIterator end)
{
content.assign(beg,end);
make_heap(content.begin(), content.end(), cmp());
}

void push(const Elem &x)
{
content.push_back(x);
push_heap(content.begin(),content.end(),cmp());
}
void pop()
{
pop_heap(content.begin(),content.end(),cmp());
content.pop_back();
}
void decreaseKey(int key, int value)
{
auto idx = find_if(content.begin(), content.end(), [& key](const Elem & x){return key==x.first;});
if(idx==content.end())
{
cout << "error : input illegal!!" << endl;
return;
}
if((*idx).second <= value)
{
return;
}
(*idx).second=value;
push_heap(content.begin(), idx+1,cmp());
}
bool empty() const
{
return content.empty();
}
Elem min() const
{
if(empty())
throw runtime_error("empty heap...");

return content[0];
}
};

#endif  /*_HEAP_H*/

//Prim

void Prim(int start)
{
Heap h;
//record the cost of each node
int min_cost[V];
fill_n(min_cost, V,100);

//record the node is in the MST or not
bool used[V];
fill_n(used,V,false);

//record the prev node inserted to the MST
bool parent[V];
fill_n(parent,V,false);

int total_cost=0; //record cost

used[start] = true;
min_cost[start]=0;
h.push(make_pair(0,0));

for(int i=1;i cost[cur][adj])
{
h.decreaseKey(adj,cost[cur][adj]);
parent[adj] = cur;
min_cost[adj]=cost[cur][adj];
}
}
}
cout << "MST =" << total_cost << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Minimum Span Tree Prim