Kruskal算法--学习笔记

Kruskal算法和哈夫曼树和并查集很像。

 这样,这四个顶点的图就被连通了,此时由parent[]数组可知,这个图的根顶点是0,因为parent[0]=-1, 其他的都保存的是他们的双亲顶点,如parent[2]=0, 表示顶点2和0是连通的

 

Kruskal的存储结构:        

#include<iostream>
using namespace std;

#define MaxSize 100
typedef struct{
	int begin;      //起始顶点
	int end;        //结束顶点
	int weight;     //这两个顶点之间的代价值
}EdgeType;

typedef struct {
	EdgeType edge[MaxSize];      //一个如下图中edge类型的变量
	int vertex[MaxSize];         /保存着各个顶点的信息
	int vertexNum, arcNum;
}Graph;

 

思路:                                                                                                                                                  

设置一个parent[]数组,用于记录顶点是否已经加入生成树。

对着G.ArcNum条边进行遍历,判断每条边连接的两个顶点是否加入了生成树,若没加入,则加入生成树。                                           

创建图:


void CreatGraph(Graph &G, int n, int e, int arr[])
{
	G.vertexNum = n;
	G.arcNum = e;
	
	for(int i=0; i<G.vertexNum; i++)
	{
		G.vertex[i] = arr[i];
	}
	
	for(int i=0; i<G.arcNum; i++)
	{
		int a,b,w;
		cin>>a>>b>>w;
		
		G.edge[i].begin = a;
		G.edge[i].end = b;
		G.edge[i].weight = w;
	}
}


int main()
{
	int n,e,mincost;
	cin>>n>>e;
	
	int arr[n];
	for(int i=0; i<n; i++)
	{
		cin>>arr[i];
	}
	
	Graph G;
	CreatGraph(G,n,e,arr);
	Kruskal(G,mincost);
	cout<<"mincost="<<mincost<<endl;
	return 0;
}

Kruskal: 

有一个parent[]数组,若 i 顶点是根节点的时候,parent[i] =-1 保存的值是-1,若 i 顶点不是根节点,parent[i] = j, 数组保存的是双亲节点,即 顶点 j是i的双亲顶点。

是一个根据weight值从小到大排序的一个数组。

Kruskal的edge数组有三个变量,begin,end, weight分别表示一条边的起始顶点,尾顶点,和这条边的权值。

开始遍历图中的每一条边,当两个顶点根节点不同时,说明来自两个不同的子树,那么就将这两个子树连线,

当树中所有顶点都连通后(也就是num==G.vertexNum-1),即可退出

或者图的所有边都遍历结束,则退出。

 最小生成树Kruskal代码:                                                                                                                

void Kruskal(Graph &G, int &mincost)
{
    mincost=0;
	sort_(G);	//对edge数组按照weight从小到大的顺序排序, 这样一定是从代价小的边选择。
	
	int parent[MaxSize];         //用于记录是否已经加入生成树和哪些顶点是一组的
	
    //初始化parent[]数组为-1, 这样每个顶点都是独立的,
	for(int i=0; i<G.vertexNum; i++)
	{
		parent[i]=-1;
	 } 
	 
	 int num=0;   //用于记录有多少个顶点加入了生成树,当所有顶点加入生成树后,则退出
	 
    //遍历所有的边
	 for(int i=0; i<G.arcNum; i++)
	 {
        //找到两个顶点的根节点,如果根节点相同,说明这两个顶点是同一组,则不连线
        //如果两个跟顶点不同,则这两个顶点没连通,我们要把他们连通
	 	int vex1 = findroot(parent, G.edge[i].begin);   
	 	int vex2 = findroot(parent, G.edge[i].end);
	 	
	 	if(vex1 != vex2)  //说明两个顶点是不同的两个子树上, 现在把这两个子树连接起来
		{
			cout<<" ( "<<G.edge[i].begin<<", "<<G.edge[i].end<<" )"<<G.edge[i].weight<<endl;
            mincost += G.edge[i].weight; 
			parent[vex1]=vex2;
			
			num++;
			if(num==G.vertexNum-1)   //如果所有顶点都加入了生成树,则退出
			{
				return;
			}
		}
	}
	
}

找到顶点的根节点 和sort函数,对数组按照weight从小到大排序

int findRoot(int parent[], int v){
    int t = v;

    while(parent[t]>-1;){
        t = parent[t];        //因为parent[t]中存储的就是双亲的位置,
    }
    return t;
}

void sort_(Graph &G)    //sort别忘了引用的方式修改变量G, 
{
	for(int i=0; i<G.arcNum-1; i++)
	{
		for(int j=1; j<G.arcNum-i; j++)
		{
			if(G.edge[j-1].weight > G.edge[j].weight)
			{
				EdgeType tmp = G.edge[j-1];
				G.edge[j-1]=G.edge[j];
				G.edge[j]=tmp;
			}
		}
	}
}

练习:

 

6 10
0 1 2 3 4 5
0 1 6
0 2 1
0 3 5
1 2 5
1 4 3
2 3 5
2 4 6
2 5 4
3 5 2
4 5 6

结果:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值