您的位置:首页 > 其它

图论;克鲁斯卡尔算法;最小生成树;通过权值排序可以优化时间效率;

2010-04-03 21:25 387 查看
#include <iostream>
using namespace std;

#define NoEdge 1000//

//无向图的邻接矩阵定义
typedef struct
{
char *vertics;//存放图中结点
int **edge;//存放邻接矩阵
int num;//存放图中顶点数量
}Graph;

//克鲁斯卡尔求最小生成树
class Kruskal
{
private:
Graph graph;//求最小生成树的图
int *set;//用于记录不同的连通分量
public:
//构造函数
Kruskal(int num)
{
set=new int[num+1];
graph.num=num;
graph.vertics=new char[num+1];
graph.edge=new int* [num+1];
int i=0;
while(i<=num)
{
graph.edge[i]=new int[num+1];
++i;
}
}
//输入图的信息
void input()
{
cout<<"输入图中顶点信息(char),按1-n输入"<<endl;
int i=1;
while(i<=graph.num)
{
cin>>graph.vertics[i++];
}
cout<<"下面输入边的权值,如果没有连接,输入1000"<<endl;
int j;
for(i=1;i<=graph.num;i++)
{
for(j=i+1;j<=graph.num;j++)
{
cout<<"输入"<<graph.vertics[i]<<"到"<<graph.vertics[j]<<"之间的权值"<<endl;
cin>>graph.edge[i][j];
}
}
}
//Kruskal求最小生成树
void kruskal()
{
int min;//用于记录最小权边
int low;//用于记录最小权边的较小序号端点
int high;//用于记录最小权边的较大序号端点
int count=1;
//初始化每个顶点都分别属于不同的集合
for(int i=1;i<=graph.num;i++)
{
set[i]=i;
}
//num个顶点的图的最小生成树有num-1条边
while(count<=graph.num-1)
{
//寻找一个权值最小的且未加入到最小生成树中的边,更好的办法是在这之前把边按权值排序存储在一个结构体数组中
//在这里可以顺序取就可以了,可以把时间复杂度从n3降到n2
min=NoEdge;

for(int i=1;i<=graph.num;i++)
{
for(int j=i+1;j<=graph.num;j++)
{
if(graph.edge[i][j]<min)
{
min=graph.edge[i][j];
low=i;
high=j;
}
}
}
//图可能没有最小生成树
if(min==NoEdge)
{
cout<<"无法生成最小生成树"<<endl;
return;
}
//找到一条最小的边,如果他们属于不同的分量,则可以加入生成树中
if(set[low]!=set[high])
{
cout<<"第"<<count<<"条边被加入"<<"连接"<<graph.vertics[low]<<"与"<<graph.vertics[high]<<endl;
//把较大序号的连通分量容纳入较小序号的连通分量当中
for(int m=1;m<=graph.num;m++)
{
if(set[m]==set[high])
{
set[m]=set[low];
}
}
++count;
}
//已经检查过的边下一次不会再被检查
graph.edge[low][high]=NoEdge;
}
}
};

void main()
{
Kruskal test(7);//7个顶点
test.input();//输入顶点与边的信息
test.kruskal();//克鲁斯卡尔算法求最小生成树
}

//测试用图的邻接矩阵如下:
//      a   b   c   d   e
//  a      50  60 1000 1000
//  b          1000 65  40
//  c              52  1000
// d                   50
// e


 

利用set集合来区分连接过程中的不同连接分量, 不同连通分量的顶点,其set值一定不同,所以可以很容易区分是否会形成回路.

如果set值不同,说明这条最小边加入后不会形成一个回路,符合最小生成树的一部分,根据贪心策略是应该加入进去的.

n个顶点的图的最小生成树有n-1条边,所以当进行了n-1次连通分量合并之后最小生成树也就完成了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐