简体   繁体   中英

Segmentation fault (core dumped) implementing union-find C++

I'm doing Kruskal minimum spanning tree and wrote some union-find function to do the set operations. Previously it worked fine, until I changed KruskalMST() function from pass-by-value to pass-by-reference. Now it look like this:

vector<Edge*> KruskalMST(vector<Edge>& EV, vector<Node>& mynodelist){
    int setcount = NVAR;
    vector<Edge*> mst;   //mst
    vector<int> umark;         //setmark
    for(int i=0;i<NVAR;i++)
    {
      umark.push_back(i);
    }


    /*Kruskal*/    
    while(setcount>1){
        cout<<"# USER DEFINED EDGES = "<<USER_DEFINED_EDGES<<endl;
        cout<<"Threshold = "<<THRESHOLD<<endl;
        cout<<"# edges = "<<EV.size()<<endl;

        for(int j = 0; j < EV.size(); j++){
            cout<<"Find(v1) = "<<Find(&mynodelist[EV[j].readv1()->readi()])->readi()<<endl;
            cout<<"Find(v2) = "<<Find(&mynodelist[EV[j].readv2()->readi()])->readi()<<endl;
            if(Find(&mynodelist[EV[j].readv1()->readi()])->readi()!= Find(&mynodelist[EV[j].readv2()->readi()])->readi()){

                mst.push_back(&EV[j]);                  //add this edge to mst
                cout<<"mst.size() = "<<mst.size()<<endl;    
                Union(&mynodelist[EV[j].readv1()->readi()], &mynodelist[EV[j].readv2()->readi()]);          //
                cout<<"after Find(v1) = "<<Find(&mynodelist[EV[j].readv1()->readi()])->readi()<<endl;
                cout<<"after Find(v2) = "<<Find(&mynodelist[EV[j].readv2()->readi()])->readi()<<endl;
            }
        }
      cout<<"it never reaches here"<<endl;
      std::list<int> listmark;
      for(int i=0;i<NVAR;i++){
         mynodelist[i].setmark(Find(&mynodelist[i]));
         listmark.push_back(mynodelist[i].readmark());
      }
      listmark.sort();
      listmark.unique();
      setcount = listmark.size();

      umark.clear();
      umark.insert(umark.begin(), listmark.begin(),listmark.end());   //assign list to vector (clear first)


      cout << "# disjoint components: " << setcount << endl;
      cout << endl;

      }
    return mst;
    }

The strange thing is that it ran for sometime and crashed, yielding

All Vertices: #100
All Edges: #4950
# USER DEFINED EDGES = 0
Threshold = 15
# edges = 4950
Find(v1) = 96
Find(v2) = 36
mst.size() = 1
after Find(v1) = 96
after Find(v2) = 96
Find(v1) = 81
Find(v2) = 48
mst.size() = 2
after Find(v1) = 81
after Find(v2) = 81
...
...
Find(v1) = 57
Find(v2) = 84
mst.size() = 26
after Find(v1) = 84
after Find(v2) = 84
Find(v1) = 29
Segmentation fault (core dumped)

It seems it crashes at random number of iterations, but never got out of that for loop. What is the possible cause for this? Help me please!

EDIT

The Find and Union functions:

Node* Find(Node* node) {          //FINDING THE REPRESENTATIVE FOR EACH SET
    Node* temp;
    Node* root = node;

    while (root->readp() != NULL)
        root = root->readp();    //readp() reads its parent

    /* Updates the parent pointers */
    while (node->readp() != NULL) {
        temp = node->readp();
        node->setp(root);   //setparent
        node = temp;
    }

    return root;
}


/* Merges two nodes based on their rank */
void Union(Node* node1, Node* node2) {
    Node* root1 = Find(node1);
    Node* root2 = Find(node2);

    if (root1->readrank() > root2->readrank()) {                //WHOSE RANK IS LARGER, WHO'S THE PARENT. RANK IS THE NUMBER OF CHILDREN FOR THE VERTEX
        root2->setp(root1);
    } else if (root2->readrank() > root1->readrank()) {
        root1->setp(root2);
    } else {                                        //EQUAL, ROOT1'S RANK INCREMENTS AND IS THE PARENT
        root2->setp(root1);
        root1->setrank((root1->readrank())+1);
    }
}

I didn't change Union-find part, just changed KruskalMST(vector<Edge> EV, vector<Node> mynodelist) to KruskalMST(vector<Edge>& EV, vector<Node>& mynodelist)

Your return vector is of pointers, but the passed vectors take items by value. When you build the results you are pushing on pointers to the values in the passed EV vector. This is not a safe. If at any time you change the passed EV vector -- during the function or even after KrustalMST() returns -- the address of the values in that vector will change. Thus accessing the returned pointers will be invalid.

If the KruskalMST() method was taking the parameters by value, that would make the situation worse, because you would return pointers to elements in a destroyed vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM