最小生成树Kruskal算法实现C++实现

 

// Kruskal算法实现.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#define MAX 100
typedef  int WeiType;
using namespace std;

//
struct Edge
{
 int no;   //边的序号
 int x;    //端点1序号
 int y;    // 端点2序号
 WeiType weight;   //权值
 bool selected; //是否被选择
};

//边集和
Edge edge[MAX];
//已找到的最小生成树其中一部分的秩
int rank[MAX];
//已找到的最小生成树其中一部分的头结点
//用来判断一条边的2个端点是否在一个集合中,即加上这条边是否会形成回路
int parent[MAX];

//找出每一集合的头结点
int find_set(int x)
{
 if(x != parent[x] )
  parent[x] = find_set(parent[x]);
 return parent[x];
}

//合并集合
void union_set(int x,int y,WeiType w,WeiType &sum)
{
 if(x==y)
  return;
 if(rank[x]>rank[y])
  parent[y]=x;
 else
 {
  if(rank[x]==rank[y])
   rank[y]++;
  parent[x]=y;
 }
 sum +=w;
}

//依据边的权值升序快速排序
void fast_sort(Edge *edge,int begin,int end)
{
 if(begin<end)
 {
  int i = begin-1,j=begin;
  edge[0] = edge[end];
  while(j<end)
  {
   if(edge[j].weight<edge[0].weight)
   {
    i++;
    Edge temp1 = edge[i];
    edge[i] = edge[j];
    edge[j] = temp1;
   }
   j++;
  }
  Edge temp2 = edge[end];
  edge[end] = edge[i+1];
  edge[i+1] = temp2;
  fast_sort(edge,begin,i);
  fast_sort(edge,i+2,end);
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 int cases;
 cout<<"请输入案例的个数:";
 cin>>cases;
 while(cases--)
 {
  int n;
  //最小生成树的权值总和
  WeiType sum = 0;
  cout<<"请输入边的个数:";
  cin>>n;
  int i;
  //初始化
  char chx,chy;
  WeiType weight;
  for(i=1;i<=n;i++)
  {
   edge[i].no = i;
   cout<<"请输入第"<<i<<"条边的二个端点的名称(小写字符):";
   cin>>chx>>chy;
   edge[i].x = chx-'a'+1;
   edge[i].y = chy-'a'+1;
   cout<<"这条边的权值为:";
   cin>>weight;
   edge[i].weight = weight;
   edge[i].selected = false;
   parent[edge[i].x] = edge[i].x;
   parent[edge[i].y] = edge[i].y;
   rank[edge[i].x] = 0;
   rank[edge[i].y] = 0;
  }
  //快排
  fast_sort(edge,1,n);
  for(i=1;i<=n;i++)
  {
   int x,y;
   x = find_set(edge[i].x);
   y = find_set(edge[i].y);
   //判断即加上这条边是否会形成回路
   if(x != y )
   {
    //选择这条边
    edge[i].selected = true;
    //合并不会形成回路的二个集合
    union_set(x,y,edge[i].weight,sum);
   }
  }
  cout<<"最小生成树的边集为:"<<endl;
  for(i=1;i<=n;i++)
  {
   if(edge[i].selected)
   {
    cout<<"序号:"<<edge[i].no<<"  " <<"端点1:"<<(char)(edge[i].x+'a'-1)<<",端点2:"<<(char)(edge[i].y+'a'-1)<<endl;
   }
  }
  cout<<"最小生成树的权值为:"<<sum<<endl;
 }
 system("pause");
 return 0;
}

-------------------------------------------程序测试-------------------------------------------

                                     

请输入案例的个数:1
请输入边的个数:14
请输入第1条边的二个端点的名称(小写字符):a b
这条边的权值为:4
请输入第2条边的二个端点的名称(小写字符):a h
这条边的权值为:8
请输入第3条边的二个端点的名称(小写字符):b c
这条边的权值为:8
请输入第4条边的二个端点的名称(小写字符):b h
这条边的权值为:11
请输入第5条边的二个端点的名称(小写字符):c d
这条边的权值为:7
请输入第6条边的二个端点的名称(小写字符):c f
这条边的权值为:4
请输入第7条边的二个端点的名称(小写字符):c i
这条边的权值为:2
请输入第8条边的二个端点的名称(小写字符):d e
这条边的权值为:9
请输入第9条边的二个端点的名称(小写字符):d f
这条边的权值为:14
请输入第10条边的二个端点的名称(小写字符):e f
这条边的权值为:10
请输入第11条边的二个端点的名称(小写字符):f g
这条边的权值为:2
请输入第12条边的二个端点的名称(小写字符):g h
这条边的权值为:1
请输入第13条边的二个端点的名称(小写字符):g i
这条边的权值为:6
请输入第14条边的二个端点的名称(小写字符):h i
这条边的权值为:7
最小生成树的边集为:
序号:12  端点1:g,端点2:h
序号:11  端点1:f,端点2:g
序号:7  端点1:c,端点2:i
序号:1  端点1:a,端点2:b
序号:6  端点1:c,端点2:f
序号:5  端点1:c,端点2:d
序号:3  端点1:b,端点2:c
序号:8  端点1:d,端点2:e
最小生成树的权值为:37
请按任意键继续. . .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值