C++实现PrimMST算法

一. 例题

	给一个二维数组,一行代表一个节点,第一个表示出发节点的编号,第二个表示到达节点的编号,第三个表示二者之间的权重,求最短路径。

解法一:

#include <iostream>
#include <vector>
#include <climits>

using namespace std;

const int INF = INT_MAX; // 定义一个代表无穷大的常量

void showVec(vector<int> vec)
{
    for (auto i : vec){
        cout << i << " " ;
    }
    cout << endl <<endl;
}

void showVec2(vector<vector<int>>& graph)
{
    int n = graph.size();
    for (int i = 0; i < n; ++i){
        for (int j = 0; j < n; ++j){
            cout << graph[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl << endl;
}

int prim(vector<vector<int>>& graph) {
    int n = graph.size(); // 获取节点的数量
    vector<int> dist(n, INF); // 保存顶点到最小生成树的距离
    vector<bool> selected(n, false); // 记录顶点是否被选中
    int res = 0; // 记录最小生成树的总长度
    
    dist[0] = 0; // 从任意一点开始构建最小生成树
    
    // 遍历n个节点进行最小生成树的构建
    for (int i = 0; i < n; i++) {
        int minDist = INF; // 保存距离最小生成树最近的顶点的距离
        int minDistVertex = -1; // 保存距离最小生成树最近的顶点的索引号
        // 在尚未选中的顶点中,选择距离最小生成树最近的顶点
        for (int j = 0; j < n; j++) {
            if (!selected[j] && dist[j] < minDist) {
                minDist = dist[j];
                minDistVertex = j;
            }
        }
        
        selected[minDistVertex] = true; // 将选中的顶点标记为已选
        
        // 更新与选中顶点的相邻顶点的距离
        for (int j = 0; j < n; j++) {
            // 如果相邻顶点未选中且与选中顶点有边,并且其距离小于当前记录的距离,则更新距离
            showVec(dist);
            showVec2(graph);
            if (graph[minDistVertex][j] != INF && !selected[j] && graph[minDistVertex][j] < dist[j]) {
                dist[j] = graph[minDistVertex][j];
            }
        }
    }
    
    // 计算最小生成树的总长度
    for (int i = 0; i < n; i++) {
        res += dist[i];
    }
    
    return res; // 返回最小生成树的总长度
}

int main() {
    int n;
    cin >> n; // 输入节点的数量
    
    vector<vector<int>> graph(n, vector<int>(n, INF)); // 创建一个邻接矩阵,初始距离都为无穷大
    
    // 输入节点之间的连接关系
    for (int i = 0; i < n * (n - 1) / 2; i++) {
        int u, v, length;
        cin >> u >> v >> length;
        u--; // 顶点编号从1开始,转变为从0开始
        v--;
        graph[u][v] = graph[v][u] = length; // 无向图,两个方向都要设置距离
    }
    showVec2(graph);
    int minLen= prim(graph); // 执行prim算法得到最小生成树的总长度
    
    cout << minLen<< endl; // 输出最小生成树的总长度
    
    return 0;
}

解法二

#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
struct Edge;
struct Node{
public:
    Node(int val, int in = 0, int out = 0)
        :_val(val)
        ,_in(in)
        ,_out(out){}

    bool operator()(const Node& a, const Node& b){
        return a._val < b._val;
    }
    bool operator<(const Node& other){
        return this->_val < other._val;
    }
public:
    int _val;
    int _in;
    int _out;
    unordered_set<shared_ptr<Node>> _nextNodes;
    unordered_set<shared_ptr<Edge>> _nextEdges;
};

struct Edge{
public:
    Edge(int weight,shared_ptr<Node> from = nullptr, shared_ptr<Node> to = nullptr)
        :_weight(weight)
        ,_fromNode(from)
        ,_toNode(to)
        {}

     bool operator()(const Edge& a, const Edge& b)const{
        return a._weight < b._weight;
    }

    bool operator<(const Edge& other)const{
        return this->_weight < other._weight;
    }
public:
    int _weight;
    shared_ptr<Node> _fromNode;
    shared_ptr<Node> _toNode;
};

class Graph{
public:
    Graph(vector<vector<int>> data){
        create(data);
    }
    void create(vector<vector<int>> data);
    int PrimMST();
private:
    void showmap();

public:
    map<int, shared_ptr<Node>> _graphNodes;
    set<shared_ptr<Edge>> _graphEdges;
};

void Graph::showmap(){
    for (auto m : _graphNodes){
        //cout << "key = " << m.first << " value = " << endl;
        printf("key = %d, value = %p\n", m.first, m.second.get());
    }
}

void Graph::create(vector<vector<int>> data){
    if (data.empty()){
        return;
    }

    for (auto node : data){
        int from = node[0];
        int to = node[1];
        int weight = node[2];
        cout << "from = " << from << " to = " << to  << " weight = " << weight << endl;
        if (this->_graphNodes.find(from) == this->_graphNodes.end()){
            //Node* fromNode = new Node(from);
            shared_ptr<Node> fromNode(new Node(from));
            this->_graphNodes.insert(make_pair(from, fromNode));
        }

        if (this->_graphNodes.find(to) == this->_graphNodes.end()){
            //Node* toNode = new Node(to);
            shared_ptr<Node> toNode(new Node(to));
            this->_graphNodes.insert(make_pair(to, toNode));
        }

        auto fromNode = this->_graphNodes.find(from)->second;
        auto toNode = this->_graphNodes.find(to)->second;
        
        shared_ptr<Edge> newEdge(new Edge(weight, fromNode, toNode));
        fromNode->_out++;
        toNode->_in++;
        fromNode->_nextNodes.insert(toNode);
        fromNode->_nextEdges.insert(newEdge);
        this->_graphEdges.insert(newEdge);
    }
    showmap();
    cout << endl;
}

int Graph::PrimMST(){
    if (this->_graphEdges.empty()){
        return 0;
    }
    unordered_set<shared_ptr<Edge>> result;
    set<shared_ptr<Node>> myset;
    priority_queue<shared_ptr<Edge>> myQueue;


    for (auto node : this->_graphNodes){
        if (myset.find(node.second) == myset.end()){
            myset.insert(node.second);
        }

        for (auto edge : node.second->_nextEdges){
            myQueue.push(edge);
        }

        while (!myQueue.empty()){
            auto edge1 = myQueue.top();
            myQueue.pop();

            auto toNode = edge1->_toNode;
            if (myset.find(toNode) == myset.end()){
                myset.insert(toNode);
                result.insert(edge1);

                for (auto nextedge : toNode->_nextEdges){
                    myQueue.push(nextedge);
                }
            }
        }
    }

    int res = 0;
    for (auto i : result){
        cout << "weight = " << i->_weight << endl;
        res += i->_weight;
    }

    return res;
}

void test(){
    vector<vector<int>> data{{1,2,5},{1,3,6},{2,3,7}};
    Graph graph(data);
    int result = graph.PrimMST();
    cout << "result = " << result << endl;
}

int main(void){
 test();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值