最小生成树(克鲁斯卡尔算法)数据结构

思路

  1. 双亲表示法
    用双亲表示法表示单个集合,其中双亲作为标记,在同一个连通分量里的点双亲相同(需要在开始就将双亲设置,后面会与权值比较,所以越大越好,但开始都不相同)
  2. 三元组
    三元组表示要输入的形式
  3. 迭代找最小权值
    在找到权值并使用后,将其变成负数,最后输出时要变回来

问题描述:

见习题集P152。用克鲁斯卡尔(Kruskal)算法求无向网的最小生成树。

输入:
输入数据第一行为两个正整数n(1<n<=30)和m(1<m<100),分别表示顶点数和边数。后面紧跟m行数据,每行数据是一条边的信息,包括三个数字,分别表示该边的两个顶点和边上的权值。
输出:
按顺序输出Kruskal算法求得的最小生成树的边集,每行一条边,包括三个数字,分别是该边的两个顶点和边上的权值,其中第一个顶点的编号应小于第二个顶点的编号。
示例输入
8 11
1 2 3
1 4 5
1 6 18
2 4 7
2 5 6
3 5 10
3 8 20
4 6 15
4 7 11
5 7 8
5 8 12
示例输出
1 2 3
1 4 5
2 5 6
5 7 8
3 5 10
5 8 12
4 6 15

#include<stdio.h>
# define max_tree_size 100

typedef struct NODE{//边的定义 
	int parent;//双亲的位置 (如果双亲相同,就在同一个集合里)
	//int next;//相关联的节点位置 
	int date;//自己点的位置 
}D[100]; 
typedef struct tri{//三元组 
	int x;//前继 
	int y;//后继 
	int weigh;//权值 
}T[100]; 
typedef struct TREE{
	tri T[100];//边的集合 
}Tree;

int findmin(tri T[],int m,NODE D[]){//找最小的边
	int min=999;
	int temp;
	for(int j=0;j<m;j++){//在满足条件的情况下,直接找最小
		if(T[j].weigh<=min&&T[j].weigh>0) {
		min=T[j].weigh;
		temp=j;
		}
	} 
	if(D[T[temp].x ].parent ==D[T[temp].y ].parent )	{
		T[temp].weigh =999999;
		findmin(T,m,D);
	}//相等说明已经在一个集合了,该路径不能走,直接999999,再也走不通 
	else {
		if(D[T[temp].x ].parent<D[T[temp].y ].parent){//因为权值总是从小到大被发现,可作为双亲 ,
		//前提是最开始的双亲都大于最小的权值 
			if(D[T[temp].x ].parent>T[temp].weigh){// 找出x,y的双亲最小的那个与当前所找到的权值比较,取较小的 
				D[T[temp].x ].parent=T[temp].weigh;//这样能保证在同一个连通分量总能有相同的双亲 
				D[T[temp].y ].parent=T[temp].weigh;//在不同的连通分量有不同的双亲 
			}
			else D[T[temp].y ].parent=D[T[temp].x ].parent;
		} 
		else{
			if(D[T[temp].y ].parent>T[temp].weigh){
				D[T[temp].x ].parent=T[temp].weigh;
				D[T[temp].y ].parent=T[temp].weigh;
			}
			else D[T[temp].x ].parent=D[T[temp].y ].parent;
		}
		T[temp].weigh=T[temp].weigh*(-1);//为了防止下一次还找到该路径,将权值改为负数,输出时需要改回来 
		return temp;
	}//成功找到,将双亲设为一样 ,在一个集合的点的双亲需要一起变 
}
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	tri T[100]; 
	NODE D[100];
	Tree p; 
	int i,j,k,count=0;
	for(i=999;i<n+999;i++)	D[i].parent =i;//设置一下双亲,每都不一样 ,放到一个集合(连通分量)时就让他们一样 
	for(i=0;i<m;i++)	scanf("%d %d %d",&T[i].x ,&T[i].y ,&T[i].weigh );//输入三元组
	for(i=0;i<n-1;i++){//循环顶点数-1次即可,就会连通 
		k=findmin(T,m,D);
		p.T[count]=T[k];//将找到的路径存入树中,觉得这里有点滑稽,感觉自己骗自己,直接输出就完了 
		count++;
		printf("%d %d %d\n",p.T[i].x ,p.T[i].y,p.T[i].weigh*(-1) ); 
	}
}

感想

样例只过了一个,因为oj时间截止了,各位如果发现什么错误,欢迎指正。
感觉自己代码还是很复杂,向大家请教更简单的思路
菜鸡一个的我,希望大家找我交流
期末了,要疯狂肝数据结构的题了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值