【问题标题】:Segmentation Fault in C++ implementation of Kruskal's AlgorithmKruskal 算法的 C++ 实现中的分段错误
【发布时间】:2020-07-05 02:41:48
【问题描述】:

我编写了这段代码,它实现了 Kruskal 的最小生成树算法,当我将它提交给在线法官时,它会产生分段错误。我想我已经将分段错误的原因缩小到我对边缘进行排序的部分。尽管如此,我还是找不到这段代码失败的确切原因。

struct DisjointSet{
    private:
        struct Node{
            int size;
            int repr;
            Node(int rep){
                size = 1;
                repr = rep;
            }
        };
        vector<Node> nodes;
    public:
        int makeSet(){
            nodes.push_back(Node(nodes.size()));
            return nodes.size() - 1;
        }
        int findRepresentative(int ind){
            if(nodes[nodes[ind].repr].size == -1){
                nodes[ind].repr = findRepresentative(nodes[ind].repr);
            }
            return nodes[ind].repr;
        }
        void unionSets(int ind1, int ind2){
            int rep1 = findRepresentative(ind1), rep2 = findRepresentative(ind2);
            if(rep1 != rep2){
                if(nodes[rep1].size < nodes[rep2].size){
                    int t = rep1;
                    rep1 = rep2;
                    rep2 = t;
                }
                nodes[rep1].size += nodes[rep2].size;
                nodes[rep2].size = -1;
                nodes[rep2].repr = rep1;
            }
        }
};

bool compare(const pair<pair<int, int>, int> &p1, const pair<pair<int, int>, int> &p2){
    return (p1.second <= p2.second);
}

int spanningTree(int V, int E, vector<vector<int>> &graph) {
    vector<pair<pair<int, int>, int>> edges;
    for(int i = 0;i < V;i ++){
        for(int j = 0;j < V;j ++){
            if(i <= j){
                if(graph[i][j] != INT_MAX){
                    edges.push_back(make_pair(make_pair(i, j), graph[i][j]));
                }
            }
        }
    }
    sort(edges.begin(), edges.end(), compare);
    DisjointSet d;
    for(int i = 0;i < V;i ++){
        d.makeSet();
    }
    int weight = 0;
    for(int i = 0;i < edges.size();i ++){
        int u = edges[i].first.first, v = edges[i].first.second;
        if(d.findRepresentative(u) != d.findRepresentative(v)){
            d.unionSets(u, v);
            weight += edges[i].second;
        }
    }
    return weight;
}

【问题讨论】:

  • 您是否尝试过使用调试器在崩溃发生时捕捉崩溃,并准确地在代码中找到它发生的位置?它还允许您在崩溃时检查所有相关变量的值,以确保它们都是有效的(即没有越界索引等)
  • 你的比较函数没有实现严格的弱排序。
  • @Someprogrammerdude 运行代码的测试是由在线评委提供的,所以我无法确定代码是如何失败的。但是,我使用了另一个 Prim 的算法实现,并使用它来定位错误的原因。它似乎来自我对边缘进行排序的行。

标签: c++ segmentation-fault kruskals-algorithm


【解决方案1】:

您的比较功能:

bool compare(const pair<pair<int, int>, int> &p1, const pair<pair<int, int>, int> &p2){
    return (p1.second <= p2.second);
}

不提供严格-弱排序,因为比较两个元素 e1e2 与相同的 .second 将返回 true both e1 &lt; e2 and em>e2 &lt; e1,这是不允许的。在排序中使用此compare 函数会调用未定义的行为,可能会导致段错误。

您需要执行以下操作:

bool compare(const pair<pair<int, int>, int> &p1, const pair<pair<int, int>, int> &p2){
    return p1.second < p2.second;
}

【讨论】:

    猜你喜欢
    • 2017-07-04
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    相关资源
    最近更新 更多