使用Kruskal算法求最小生成树

#include <iostream>  
#include <vector>  
#include <queue>  
#include <functional>  
#include <limits>  
  
using namespace std;  
  
// 图的邻接表表示  
struct ArcNode {  
    int adjVex;       // 该弧所指向的顶点的位置  
    int weight;       // 权重  
    ArcNode* next;    // 指向下一条弧的指针  
};  
  
struct VNode {  
    char data;        // 顶点信息  
    ArcNode* firstArc; // 指向第一条依附该顶点的弧的指针  
};  
  
struct ALGraph {  
    int vexNum, arcNum; // 图的当前顶点数和弧数  
    VNode vertices[100]; // 顶点表  
};  
  
// 并查集节点  
struct UFSNode {  
    int parent;  
    int rank;  
};  
  
// 并查集  
struct UFSet {  
    UFSNode* nodelist;  
    int length;  
};  
  
// 优先队列元素  
struct Edge {  
    int u, v;  
    int weight;  
};  
  
// 最小堆优先队列  
struct Compare {  
    bool operator()(const Edge& a, const Edge& b) {  
        return a.weight > b.weight;  
    }  
};  
  
// 初始化并查集  
void InitUFSet(UFSet& S, int size) {  
    S.nodelist = new UFSNode[size];  
    S.length = size;  
    for (int i = 0; i < size; ++i) {  
        S.nodelist[i].parent = i;  
        S.nodelist[i].rank = 0;  
    }  
}  
  
// 查找根节点  
int UFSetFind(UFSet& S, int x) {  
    if (S.nodelist[x].parent != x) {  
        S.nodelist[x].parent = UFSetFind(S, S.nodelist[x].parent);  
    }  
    return S.nodelist[x].parent;  
}  
  
// 合并集合  
void UFSetUnion(UFSet& S, int x, int y) {  
    int rootX = UFSetFind(S, x);  
    int rootY = UFSetFind(S, y);  
    if (rootX != rootY) {  
        if (S.nodelist[rootX].rank > S.nodelist[rootY].rank) {  
            S.nodelist[rootY].parent = rootX;  
        } else if (S.nodelist[rootX].rank < S.nodelist[rootY].rank) {  
            S.nodelist[rootX].parent = rootY;  
        } else {  
            S.nodelist[rootY].parent = rootX;  
            S.nodelist[rootX].rank++;  
        }  
    }  
}  
  
// 初始化最小优先队列  
void InitMinPriorityQueue(priority_queue<Edge, vector<Edge>, Compare>& Q) {  
    while (!Q.empty()) Q.pop();  
}  
  
// 将元素压入优先队列  
void MinPriorityQueuePush(priority_queue<Edge, vector<Edge>, Compare>& Q, const Edge& e) {  
    Q.push(e);  
}  
  
// 从优先队列弹出元素  
void MinPriorityQueuePop(priority_queue<Edge, vector<Edge>, Compare>& Q, Edge& e) {  
    if (!Q.empty()) {  
        e = Q.top();  
        Q.pop();  
    }  
}  
  
// Kruskal算法求最小生成树  
void MST_Kruskal(ALGraph& G) {  
    UFSet S;  
    InitUFSet(S, G.vexNum);  
  
    priority_queue<Edge, vector<Edge>, Compare> Q;  
    InitMinPriorityQueue(Q);  
  
    for (int i = 0; i < G.vexNum; ++i) {  
        for (ArcNode* p = G.vertices[i].firstArc; p != nullptr; p = p->next) {  
            Edge e = {i, p->adjVex, p->weight};  
            MinPriorityQueuePush(Q, e);  
        }  
    }  
  
    Edge e;  
    int count = 0;  
    while (count < G.vexNum - 1) {  
        MinPriorityQueuePop(Q, e);  
        if (UFSetFind(S, e.u) != UFSetFind(S, e.v)) {  
            UFSetUnion(S, e.u, e.v);  
            cout << G.vertices[e.u].data << "---" << G.vertices[e.v].data << " (" << e.weight << ")\n";  
            count++;  
        }  
    }  
}  
  
int main() {  
    // 示例图的初始化  
    ALGraph G;  
    G.vexNum = 5;  
    G.arcNum = 6;  
    for (int i = 0; i < G.vexNum; ++i) {  
        G.vertices[i].data = 'A' + i;  
        G.vertices[i].firstArc = nullptr;  
    }  
  
    // 添加边 (注意:这里需要实现添加边的函数,为简化,直接操作内存)  
    // A-B 1  
    ArcNode* edge1 = new ArcNode{1, 1, nullptr};  
    edge1->next = G.vertices[0].firstArc;  
    G.vertices[0].firstArc = edge1;  
    // A-D 3  
    ArcNode* edge2 = new ArcNode{3, 3, nullptr};  
    edge2->next = G.vertices[0].firstArc->next;  
    G.vertices[0].firstArc->next = edge2;  
    // B-C 4  
    // ... 类似地添加其他边  
  
    // 添加 B-C, C-D, D-E, E-A, A-C 边  
    // 注意:为了简化,这里没有完整地添加所有边,且直接操作内存可能导致内存泄漏,应使用更安全的内存管理  
  
    MST_Kruskal(G);  
  
    return 0;  
}

//请注意,为了简化代码,这里直接操作内存来添加边,这在实际应用中是不推荐的。应该使用更安全的数据结构或内存管理策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值