Kruskal最小生成树

Kruskal算法似乎更加贴近贪心算法。

每次都从边集中找出权值最小的边,符合条件则组成一个小的树。

最终这些小的树会合并成最后的大树,也就是我们想要得到的生成树。

 

Kruskal算法需要用到两种数据结构:最小堆、并查集

 

初始化:

  所以节点都是一棵树,相当于初始化并查集。

  将所有边都加入到最小堆中。

 

(1)从最小堆中选出一个权值最小的边, 将此边删除。

    如果这个边的相连的两个节点在同一个集合中,

      ·   continue

    如果不在同一集合中,将两个节点加入到同一集合。

(2)循环直到count==n-1 或 最小堆中没有元素

    

typedef int Vertex;

typedef int Weight;

typedef struct ArcNode
{
    Vertex to;
    Vertex from;
    int Weight;
    strcut ArcNode *next;
}ArcNode;

typedef struct VNode
{
    Vertex id;
    ArcNode *first;
}VNode;

typedef struct LGraph
{
    VNode* Aject[MaxVertexNum];
    int v, e;
}LGraph;


void Kruskal(LGraph& G)
{
    //自定义最小堆 
    privority_queue q;
    //将边加入最小堆中 
    for(int i = 0; i < G.v; i++)
    {
        for(ArcNode* a = G.Aject[i].first; a != NULL; a = a->next)
        {
            q.push(a);
        }
    }
    //初始化并查集 
    int d[G.v];
    init(G.v, d);
    
    int count = 0;
    while(count < n-1 && !q.empty())
    {
        ArcNode* a = q.pop();
        int from = a.from;
        int to = a.to;
        
        if(find(from) == find(to))
            continue;
        else
        {
            union(from, to);
            count++;
        }
    }
}


void init(int n, int d[])
{
    for(int i = 0; i < n; i++)
    {
        d[i] = i;
    }
    
}

int find(int d[], int a)
{
    if(d[a] == a)
        return a;
    else
        d[a] = find(d[a]);
    return d[a];
}

void union(int d[], int a, int b)
{
    if(find(a) == find(b))
        return ;
    else
        d[a] = find(b);
}

 

posted @ 2019-04-22 18:43  yangzixiongh  阅读(121)  评论(0编辑  收藏  举报