【问题标题】:Bug in finding minimum spanning tree using Kruskal's algorithm使用 Kruskal 算法查找最小生成树的错误
【发布时间】:2013-06-25 01:12:01
【问题描述】:

我编写了将顶点添加到图中的代码并更新边的权重,然后找到最小生成树。我认为我已经做到了,但似乎有一些错误,但我找不到它。使用 Valgrind 的系统并在 MST 的调用中指示“大小为 4 的无效写入”和“大小为 4 的无效读取” ,但我认为它工作正常。Valgrind 的整个错误是https://docs.google.com/document/d/1_AhOdDkyZGNTBVHspyGtnSQoU1tYkm0nVA5UABmKljI/edit?usp=sharing

如下代码被like调用

CreateNewGraph();
AddEdge(1, 2, 10);
AddEdge(2, 4, 10);
AddEdge(1, 3, 100);
AddEdge(3, 4, 10);
GetMST(mst_edges);

结果将是 (1,2) (2,4) (3,4)。

然后打电话

UpdateEdge(1, 3, 0.1);
GetMST(mst_edges);

结果将是 (1,2) (1,3) (2,4)。

它被发送到系统执行,它会像上面一样被调用,但在上面的很多时间周期中。

#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

namespace HOMEWORK{
    class Edge{
        public:
            Edge(unsigned int, unsigned int, double);
            unsigned int u;
            unsigned int v;
            double w;
        friend bool operator<(const Edge& a, const Edge& b){
         return a.w < b.w;
        }
    };
    Edge::Edge(unsigned int source = 0, unsigned int destination = 0, double weight = 0.0){
        u = source;
        v = destination;
        w = weight;
    }

    vector<Edge> graph(0);
    vector<int> parent(0);

    int findset(int x){
        if(x != parent[x])parent[x] = findset(parent[x]);
        return parent[x];
    }

    void CreateNewGraph(){
        graph.clear();
        parent.clear();
    }

    void AddEdge(unsigned int u, unsigned int v, double w){
        graph.push_back(Edge(u,v,w));
    }

    void UpdateEdge(unsigned int u, unsigned int v, double w){
        for(int i = 0; i < graph.size(); i ++){
            if(graph[i].u == u && graph[i].v == v)graph[i] = Edge(u,v,w);
        }
    }

    void GetMST(vector<pair<unsigned int, unsigned int> >& mst_edges){
        mst_edges.clear();
        parent.clear();
        int e = graph.size();
        for(int i = 0; i <= e + 1; i ++)parent.push_back(i);
        stable_sort(graph.begin(), graph.end());
        for(int i = 0; i < e; i ++){
            //cout << graph[i].u << ":" << graph[i].v << ":" << graph[i].w << ":" << parent[i + 1] << endl;
            int pu = findset(graph[i].u);
            int pv = findset(graph[i].v);
            if(pu != pv){
                parent[pu] = parent[pv];
                mst_edges.push_back(make_pair(graph[i].u, graph[i].v));
            }
        }
    }

    void Init(){
    }

    void Cleanup(){
    }
}

【问题讨论】:

  • 我建议你启动你的调试器。这是每个有抱负的程序员学习的重要工具。
  • 在 Valgrind 输出中,您有文件名和问题所在的行号。先看那个。或者至少请在您提供的来源中指出问题所在的哪里。
  • 它说 HOMEWORK::GetMST(std::vector<:pair int unsigned>, std::allocator<:pair int unsigned> > > &) (code.cpp:29)该行不是代码,上面的代码似乎是正确的。
  • 您也可能拥有超出向量限制的潜在访问权限。例如,在findset 中,您访问parent[x] 而不检查x 是否是有效索引。顺便说一句,如果显示的代码是 code.cpp 的完整文件,它也恰好是第 29 行。

标签: c++ algorithm graph graph-algorithm kruskals-algorithm


【解决方案1】:

我认为问题在于您如何设置父指针。请注意,您已将 parents 设置为

for(int i = 0; i <= e + 1; i ++) parent.push_back(i);

这会在parent 数组中为图中的每条边创建一个条目,再加上一个额外的条目。但是,每个 node 都有一个父节点,而不是每个 edge,并且图中的节点数可以大于边数加一。例如,假设你有这组边:

1  2
3  4
5  6

该图显然有六个节点(编号为 1 ... 6),但您的代码只会为 parents 中的 4 个条目腾出空间。

尝试更改您的代码,以便将parents 设置为适当的大小,可能是通过在边列表中找到最大和最小编号的节点并适当地调整数组的大小。或者,考虑使用std::unordered_map&lt;int, int&gt;,如果顶点编号不连续从 0 开始,则更灵活。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2014-06-16
    • 1970-01-01
    相关资源
    最近更新 更多