最小生成树之克鲁斯卡尔算法

克鲁斯卡尔算法:
假设连通网N = {V,{E}},则令最小生成树的初始状态为只有n个顶点而无边的非连通图T = {V,{}},图中每个顶点自成一个连通分量。在E中选择一个最小代价边,若该边依附的顶点落在T中的不同连通分量上,则将此边加入到T中,否则舍去此边而选择下一条最小代价边【最小生成树不存在环】。依次类推,直至T中所有顶点都在同一连通分量上为止。【连通分量:无向图的极大连通子图】

考虑如下连通图:

最小生成树之克鲁斯卡尔算法_第1张图片

用边集数组表示为:

最小生成树之克鲁斯卡尔算法_第2张图片

注:这里为了算法方便,将边集数组内容按权值从小到大进行了排序。

下面使用克鲁斯卡尔算法构造最小生成树(对照代码):
1.初始化辅助数组(parent):


2.从已经排好序的边集数组中取出第一行数据,分别计算Find(begin)和Find(end),看是否会形成环(m==n),若不形成环,则输出,并更新辅助数组(parent[n] = m),在这里,find(0) = 0,find(2) = 2
所以将0---2这条边纳入生成树集合:
最小生成树之克鲁斯卡尔算法_第3张图片

辅助数组为:


3.第二次循环,会将3---5纳入生成树集合:

最小生成树之克鲁斯卡尔算法_第4张图片

辅助数组为:


4.如此再循环两次:

最小生成树之克鲁斯卡尔算法_第5张图片

辅助数组:


此时,再准备下次循环时,对应的是边集数组的第四组:

最小生成树之克鲁斯卡尔算法_第6张图片

计算find(0)=5,find(3)=5,即m==n,形成了环,所以被舍去!直到遇到边集数组第六组时才不会形成环。最终生成树为:

最小生成树之克鲁斯卡尔算法_第7张图片

实现:

/*******************************************
最小生成树之克鲁斯卡尔算法
by Rowandjj
2014/7/9
*******************************************/
#include
using namespace std;

#define MAX_VERTEX_NUM 20//最大顶点数

typedef struct _EDGE_
{
    int begin;//起始点序号
    int end;//终点序号
    int weight;//权值
}Edge[MAX_VERTEX_NUM];//边集数组

typedef struct _GRAPH_
{
    Edge edge;//边集数组
    int numVertiexs;//顶点数
    int numEdges;//边数
}Graph;//图存储结构--->边集数组结构

//------------------------------------------
void CreateGraph(Graph* g);//构建有权无向图g
void Display(Graph g);//输出图g的相关信息

int Find(int *parent,int f);
void MiniSpanTree_Kruskal(Graph g);//最小生成树之克鲁斯卡尔算法
//------------------------------------------
void CreateGraph(Graph* g)
{
    int i;

    cout<<"输入顶点数、边数:";
    cin>>g->numVertiexs;
    cin>>g->numEdges;

    cout<<"按权值从小到大顺序输入每条边的两个顶点及权值:"<numEdges; i++)
    {
        cin>>g->edge[i].begin;
        cin>>g->edge[i].end;
        cin>>g->edge[i].weight;
    }
}

void Display(Graph g)
{
    cout<<"顶点数:"<"< 0)
    {
        f = parent[f];
    }
    return f;
}

void MiniSpanTree_Kruskal(Graph g)//最小生成树之克鲁斯卡尔算法
{
    int i;
    int m,n;
    int parent[MAX_VERTEX_NUM];//定义辅助数组,用来判断边与边之间是否存在环路
    //1.初始化辅助数组
    for(i = 0; i < g.numVertiexs; i++)
    {
        parent[i] = 0;
    }

    //2.计算最小生成树
    for(i = 0; i < g.numEdges; i++)
    {
        n = Find(parent,g.edge[i].begin);
        m = Find(parent,g.edge[i].end);
        if(n != m)//如果没有形成c环,那么输出
        {
            parent[n] = m;//表示此顶点已经在生成树集合中
            
            cout<"<
测试:

最小生成树之克鲁斯卡尔算法_第8张图片



你可能感兴趣的:(数据结构与算法,数据结构与算法)