最小生成树——Kruskal算法

这是求无向图的最小生成树的另一算法,主要思想是每次找到一条连接不同连通分量的最小边,然后合并他连接的的这两个连通分量,直至所有的节点构成了一个连通分量(不含通路)~

算法不算难,但是也犯了些很二的错误,在下面写一下吧,当做 参考教训!

参考代码:

#include<iostream>
#include<fstream>
#include<cstring>
#include<algorithm>
using namespace std;

int graph[101][101];
int parent[101];
int node_num;

struct edge
{
	int x,y;
	int value;
};
edge e0[1001];
edge e1[101];
int edge_num=0;

void garph_to_edge()//这一步其实是多余的,完全可以直接通过edge对图进行直接存储,这里只是为了个人处理方便
{
	for(int i=0;i<node_num;i++)
	{
		for(int j=i+1;j<node_num;j++)
		{
			if(graph[i][j]<100)
			{
				e0[edge_num].x=i;
				e0[edge_num].y=j;
				e0[edge_num].value=graph[i][j];
				edge_num++;
			}
		}
	}
}

bool cmp(const edge& ee1,const edge& ee2)
{
	return ee1.value<ee2.value;
}

void combine(int i,int j)
{
	int count=parent[i]+parent[j];
	if(parent[i]>parent[j])
	{
		parent[i]=j;
		parent[j]=count;
	}
	else
	{
		parent[j]=i;
		parent[i]=count;
	}
}

int find(int i)
{
	int top=i;
	while(parent[top]>-1)
	{
		top=parent[top];
	}

	int p=i;
	while(p!=top)
	{
		int temp=parent[p];
		parent[p]=top;
		p=temp;
	}

	return top;
}

void kruskal()
{
	memset(parent,-1,(node_num+1)*sizeof(int));

	sort(e0,e0+edge_num,cmp);
	
	int pointer=0;
	int count=0;
	while(count<node_num-1)
	{
		
		int x=find(e0[pointer].x);
		int y=find(e0[pointer].y);
		if(x==y)
		{
			pointer++;
			continue;
		}
		e1[count].x=e0[pointer].x;
		e1[count].y=e0[pointer].y;
		e1[count].value=e0[pointer].value;
		combine(x,y);
		count++;
		pointer++;
	}

	for(int i=0;i<node_num-1;i++)
	{
		cout<<e1[i].x+1<<"\t"<<e1[i].y+1<<"\t"<<e1[i].value<<endl;
	}
}

int main()
{
	ifstream in;
	in.open("graph.txt",ios::in);
	in>>node_num;
	for(int i=0;i<node_num;i++)
	{
		for(int j=0;j<node_num;j++)
		{
			in>>graph[i][j];
		}
	}

	garph_to_edge();
	
	kruskal();

	return 0;
}

然后再写一下自己Coding的时候犯的一些二吧:

1.写cmp函数的时候,误把后一ee2写成了ee1,结果排不出来顺序了

2.find函数里排序的时候把sort(e0,e0+edge_num,cmp);开始误写成了sort(e0,e0+edge_num+1,cmp);结果导致增加了后面一组初值为(x,y,0)的成为了第一组,影响了结果!

2.find函数里的第一个循环的判断条件parent[top]>-1原本写成了parent[top]>0。因为之前做的时候都是从下标1开始,所以习惯了写了0,但是这次用的是从0开始,结果可想而知了...

都挺二的,但是还是错了,并且查找的时候还费了好大功夫。也许是真的这学期写的太少了,手生疏了吧,看看还得加油啦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值