#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <algorithm>
using namespace std;
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20 //顶点最多个数
#define LENGTH 5 //顶点字符长度
//********************************Kruskal(并查集实现)********************************begin
typedef struct _edge
{
int v; //起点
int w; //终点
int weight; //权值
}edge;
typedef struct _Graph
{
edge edges[MAX_VERTEX_NUM*MAX_VERTEX_NUM/2]; //弧的数组
char vexs[MAX_VERTEX_NUM][LENGTH]; //顶点数组
int vexnum; //顶点个数
int arcs; //弧的个数
}Graph;
int father[MAX_VERTEX_NUM];
int rank[MAX_VERTEX_NUM];
int LocateVex(const Graph & g, char name[LENGTH])
{
for (int i = 0; i < g.vexnum; i++)
{
if (0 == strcmp(g.vexs[i], name))
{
return i;
}
}
return -1;
}
//图的建造
void CreateGraph(Graph &g)
{
ifstream fcin(_T("kruskal.txt"));
fcin>>g.vexnum;
for (int i = 0; i < g.vexnum; i++)
{
fcin>>g.vexs[i];
}
fcin>>g.arcs;
char arcHead[LENGTH];
char arcTail[LENGTH];
int weight;
for (int i = 0; i < g.arcs; i++)
{
memset(arcHead, 0, LENGTH);
memset(arcTail, 0, LENGTH);
fcin>>arcTail>>arcHead>>weight;
int w = LocateVex(g, arcHead);
int v = LocateVex(g, arcTail);
g.edges[i].w = w;
g.edges[i].v = v;
g.edges[i].weight = weight;
}
}
int comp(const void *a,const void *b)
{
return ((edge *)a)->weight - ((edge *)b)->weight;
}
//并查集
//1、初始化
void make_set()
{
for (int i = 0; i < MAX_VERTEX_NUM; i++)
{
father[i] = i;
rank[i] = 1;
}
}
//2、查询
int find_set(int x)
{
while (x != father[x])
{
x = father[x];
}
return x;
}
//3、合并
bool Union(int first, int second)
{
int x = find_set(first);
int y = find_set(second);
if (x == y) //同一个父亲就返回
{
return false;
}
else
{
if (rank[x] > rank[y])
{
father[y] = x;
}
else
{
if (rank[x] == rank[y])
{
rank[y]++;
}
father[x] = y;
}
return true;
}
return false;
}
//kruskal算法
void MiniSpanTree_Kruskal(Graph g)
{
int count = 0;
int cost = 0;
for (int i = 0; i < g.arcs; i++)
{
if (Union(g.edges[i].w, g.edges[i].v))
{
cost += g.edges[i].weight;
count++;
cout<<"第"<<count<<"条:"<<g.vexs[g.edges[i].v]<<" "
<<g.vexs[g.edges[i].w]<<" "<<g.edges[i].weight<<endl; if (count == g.vexnum - 1)
{
break;
}
}
}
cout<<"最少花费为:"<<cost<<endl;
}
//********************************Kruskal(并查集实现)********************************end
//辅助函数,设置控制台的颜色
void SetConsoleTextColor(WORD dwColor)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == handle)
{
return;
}
SetConsoleTextAttribute(handle, dwColor);
}
int _tmain(int argc, _TCHAR* argv[])
{
Graph graph;
CreateGraph(graph);
SetConsoleTextColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
cout<<"********************Kruskal(并查集实现)**********************"<<endl<<endl;
make_set();
qsort(graph.edges, graph.arcs, sizeof(edge), comp);
MiniSpanTree_Kruskal(graph);
cout<<endl<<endl;
return 0;
}
界面运行如下:
图建造用到的kruskal.txt文件为:
6
V1 V2 V3 V4 V5 V6
10
V1 V2 6
V1 V3 1
V1 V4 5
V2 V3 5
V2 V5 3
V3 V4 5
V3 V5 6
V3 V6 4
V4 V6 2
V5 V6 6