我在C ++中实现了一个简单版本的Prim算法,并且在将算法转换为基本的图形实现时遇到了一些困难。
我有一个边缘结构,如下所示:
struct edge
{
int src;
int dest;
int weight;
};
我只是将边缘推到图类中的向量。我不确定这是否是实现Prim的最佳方式,但它似乎对我的最终结果是最佳的,它能够简单地打印出顶点的数量visitTed和最小的总重量生成树。
我想我理解Prim的基本思想,但我对几点有疑问。我要求的只是推动正确的方向。特定于我的使用的伪代码是理想的。
1)选择一个起始顶点
2)在从源顶点到所有其他循环的while循环中,将边权重添加到某种堆中(这对我来说很困惑,有些算法会说初始化为无穷大但STL优先级队列没有有储备方法......)
3)获得最低边缘(从优先级队列弹出或在我考虑不周的实现中遍历向量以获得最低值...)
4)如果访问了最低值的目的地,则抛弃该边缘并尝试下一个。如果没有,请将边缘添加到最小生成树并将其标记为已访问。
我没有太多代码,而且我的收益正在减少,所以任何建议都值得赞赏。这就是我得到的:
vector<edge> graph::prims(int source, vector<edge> vt)
{
int current;
vector<bool> visited(numVert, false);
vector<unsigned int> minWeight;
minWeight.reserve(numVert);
// Intilize minWeight to a large number
for(int j=0; j < numEdges; j++)
{
minWeight[j] = 0xffffffff;
}
current = source;
// Will this even work? What if I pick the nth node...
while (current <= numEdges)
{
// This should add the edge weights to the current vertex
// to a vector so the minimum can be found
for(int i = 0; i < numVert; i++)
{
if(vt[i].src == current && visted[i] == false)
{
minWeight.push_back(vt[i].weight);
}
}
}
// Need to finish Prim's
return vt;
}
我一直在尝试从互联网上获取代码并整天修改,这让我无处可去。所以我最终决定自己尝试一下。它并不多,但这花了我两个小时......
我的代码可以在Google Drive找到。
答案 0 :(得分:2)
我查看了您的代码,看起来您的设计在某些方面并不完整。我们来看看。
您的graph
课程如下:
class graph {
public:
... function prototypes ...
private:
int numVert;
int numEdges;
};
此类声明缺少一些相当重要的信息:特别是,在存储顶点数和边数时,不会存储有关属于给定graph
实例的顶点或边的信息。
您已经拥有edge
和city
结构,可分别用于边和顶点。这些可以存储在std::vector<...>
类的graph
成员中,并且 - 如果您小心保留相关的排序 - 您可以通过数字索引解决这些问题,并且(大部分)都可以。完成后,您可以调整addEdge
和addCity
,以便他们实际执行应有的操作 - 也就是说,分别向graph
实例添加边或顶点
要考虑的另一件事是你真正想要存储你的边缘。 “最佳”方法取决于问题的性质,但对于大多数应用程序来说,将边缘存储在由顶点ID(例如std::map<std::vector<...> >
实例)键入的结构中,或者作为每个顶点对象中的子字段就足够了(例如,通过向std::vector<...>
类添加city
成员字段。
除此之外,让我们来解决您尝试实施的实际算法。
Prim的算法,其核心是迭代应用此规则:
向候选最小生成树添加最小权重边缘,将树内部的某些顶点连接到外部的某个顶点。
也就是说,在每一步,我们都这样做:
您可以证明,在连接原始图形的情况下,此算法会生成具有最小总边缘权重的生成树。试着为自己证明这一点。
那么,你现在在哪里?虽然我无法理解你的想法,但我可以告诉你代码告诉我的内容:
std::vector<unsigned int>
来达到这个目的,因为对于给定的边缘,你需要跟踪三个量:'from'顶点,'to'顶点,以及重量。您可能需要std::vector<edge>
来代替此目的。那么,算法中缺少什么?
我希望这会帮助你。如果您对任何事情感到困惑,需要更多解释,或者认为我所说的内容不准确或不正确,请告诉我,我会更新此答案。
答案 1 :(得分:0)
//Prims Algorithm implementation using matrix in simpler way
#include<iostream>
#include<limits.h>
using namespace std;
int n=5;
//Min Node will return the node having minimum weight
int min_node(int matrix[5][5],bool visited[5]){
int result;
int min_value=INT_MAX;
for(int i=0;i<n;i++){
if(visited[i]){
for(int j=0;j<n;j++){
if(matrix[i][j]<min_value && !visited[j]){//If the node is not in visited array then consider it,otherwise not,
//to avoid the loop in the minimum spanning tree
min_value=matrix[i][j];//update the min value
result=i*10 + j;
}//endl inner if structure
}//end inner for loop
}//end outer if structure
}//end outer for loop
return result;
}
int main(){
cout<<"Hello world\n";
int matrix[5][5]={
{0,18,15,0,0},
{18,0,12,0,13},
{15,12,0,20,0},
{0,0,20,0,11},
{0,13,0,11,0}
};
//Display the matrix
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
cout<<matrix[i][j]<<"\t";
cout<<"\n";
}
//Make the disconnected node weight = MAX
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]==0)
matrix[i][j]=INT_MAX;
}
}
//Take an visited array
bool visited[5];
//Make all the entries of visited array false
for(int i=0;i<5;i++)
visited[i]=false;
int source;
cout<<"Enter the source vertex\n";
cin>>source;
visited[source]=true;
//Tree having 'n' vertices will have 'n-1' edges in the minimum spanning tree
int t=4;
while(t>0){
int result=min_node(matrix,visited);
int i=result/10;
int j=result%10;
visited[j]=true;//Now add the new node the visited, to consider the its edeges in the condition
cout<<"Path "<<i<<"- "<<j<<" ="<<matrix[i][j]<<endl;
t--;
}
return 0;
}