Implementation of Prim's algorithm in C++












2














Could anyone comment on what could be done better and if I made any mistakes?



#include <iostream>
#include <vector>
#include <algorithm>


using namespace std;

typedef pair<pair<int, int>, int> Edge; //a, b, length
// A---------B
// length


vector<Edge> prims_algo(vector<vector<int>> graph, int number_of_nodes){
vector<int> unvisited;
vector<int> visited;
vector<Edge> result;

//mark first as visited and mark the rest as unvisited
for (int i = 1; i < number_of_nodes; i++)
unvisited.push_back(i);
visited.push_back(0);

while (!unvisited.empty()) {

vector<Edge> edges_with_lengths;
//put all edges (with their lengths) from nodes that are in visited
for(auto node : visited) {
for (int sec_node = 0; sec_node < number_of_nodes; sec_node++) {
if (graph[node][sec_node] > 0 && find(unvisited.begin(), unvisited.end(), sec_node) != unvisited.end()) {
//add if there is connection and second node is not visited yet
Edge e = make_pair(make_pair(node, sec_node), graph[node][sec_node]);
edges_with_lengths.push_back(e);
}
}
}

//find the shortest edge
pair<pair<int, int>, int> the_shortest;
the_shortest = edges_with_lengths.front();
for(auto i: edges_with_lengths){
if(the_shortest.second > i.second)
the_shortest = i;
}

//add the shortest path to the result
result.push_back(the_shortest);

//remove a node that the shortest edge leads to
unvisited.erase(remove(unvisited.begin(), unvisited.end(), the_shortest.first.second), unvisited.end());

//mark this node as visited
visited.push_back(the_shortest.first.second);
};
return result;
}


int main() {
/*
2 3
(0)--(1)--(2)
| / |
6| 8/ 5 |7
| / |
(3)-------(4)
9 */
vector<vector<int>> graph =
{{{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0},
}};

vector<Edge> result = prims_algo(graph, 5);
for(auto i:result){
cout<<"EDGE [ " <<i.first.first<<", "<<i.first.second<<"], length: "<<i.second<<endl;
}

return 0;
}









share|improve this question





























    2














    Could anyone comment on what could be done better and if I made any mistakes?



    #include <iostream>
    #include <vector>
    #include <algorithm>


    using namespace std;

    typedef pair<pair<int, int>, int> Edge; //a, b, length
    // A---------B
    // length


    vector<Edge> prims_algo(vector<vector<int>> graph, int number_of_nodes){
    vector<int> unvisited;
    vector<int> visited;
    vector<Edge> result;

    //mark first as visited and mark the rest as unvisited
    for (int i = 1; i < number_of_nodes; i++)
    unvisited.push_back(i);
    visited.push_back(0);

    while (!unvisited.empty()) {

    vector<Edge> edges_with_lengths;
    //put all edges (with their lengths) from nodes that are in visited
    for(auto node : visited) {
    for (int sec_node = 0; sec_node < number_of_nodes; sec_node++) {
    if (graph[node][sec_node] > 0 && find(unvisited.begin(), unvisited.end(), sec_node) != unvisited.end()) {
    //add if there is connection and second node is not visited yet
    Edge e = make_pair(make_pair(node, sec_node), graph[node][sec_node]);
    edges_with_lengths.push_back(e);
    }
    }
    }

    //find the shortest edge
    pair<pair<int, int>, int> the_shortest;
    the_shortest = edges_with_lengths.front();
    for(auto i: edges_with_lengths){
    if(the_shortest.second > i.second)
    the_shortest = i;
    }

    //add the shortest path to the result
    result.push_back(the_shortest);

    //remove a node that the shortest edge leads to
    unvisited.erase(remove(unvisited.begin(), unvisited.end(), the_shortest.first.second), unvisited.end());

    //mark this node as visited
    visited.push_back(the_shortest.first.second);
    };
    return result;
    }


    int main() {
    /*
    2 3
    (0)--(1)--(2)
    | / |
    6| 8/ 5 |7
    | / |
    (3)-------(4)
    9 */
    vector<vector<int>> graph =
    {{{0, 2, 0, 6, 0},
    {2, 0, 3, 8, 5},
    {0, 3, 0, 0, 7},
    {6, 8, 0, 0, 9},
    {0, 5, 7, 9, 0},
    }};

    vector<Edge> result = prims_algo(graph, 5);
    for(auto i:result){
    cout<<"EDGE [ " <<i.first.first<<", "<<i.first.second<<"], length: "<<i.second<<endl;
    }

    return 0;
    }









    share|improve this question



























      2












      2








      2







      Could anyone comment on what could be done better and if I made any mistakes?



      #include <iostream>
      #include <vector>
      #include <algorithm>


      using namespace std;

      typedef pair<pair<int, int>, int> Edge; //a, b, length
      // A---------B
      // length


      vector<Edge> prims_algo(vector<vector<int>> graph, int number_of_nodes){
      vector<int> unvisited;
      vector<int> visited;
      vector<Edge> result;

      //mark first as visited and mark the rest as unvisited
      for (int i = 1; i < number_of_nodes; i++)
      unvisited.push_back(i);
      visited.push_back(0);

      while (!unvisited.empty()) {

      vector<Edge> edges_with_lengths;
      //put all edges (with their lengths) from nodes that are in visited
      for(auto node : visited) {
      for (int sec_node = 0; sec_node < number_of_nodes; sec_node++) {
      if (graph[node][sec_node] > 0 && find(unvisited.begin(), unvisited.end(), sec_node) != unvisited.end()) {
      //add if there is connection and second node is not visited yet
      Edge e = make_pair(make_pair(node, sec_node), graph[node][sec_node]);
      edges_with_lengths.push_back(e);
      }
      }
      }

      //find the shortest edge
      pair<pair<int, int>, int> the_shortest;
      the_shortest = edges_with_lengths.front();
      for(auto i: edges_with_lengths){
      if(the_shortest.second > i.second)
      the_shortest = i;
      }

      //add the shortest path to the result
      result.push_back(the_shortest);

      //remove a node that the shortest edge leads to
      unvisited.erase(remove(unvisited.begin(), unvisited.end(), the_shortest.first.second), unvisited.end());

      //mark this node as visited
      visited.push_back(the_shortest.first.second);
      };
      return result;
      }


      int main() {
      /*
      2 3
      (0)--(1)--(2)
      | / |
      6| 8/ 5 |7
      | / |
      (3)-------(4)
      9 */
      vector<vector<int>> graph =
      {{{0, 2, 0, 6, 0},
      {2, 0, 3, 8, 5},
      {0, 3, 0, 0, 7},
      {6, 8, 0, 0, 9},
      {0, 5, 7, 9, 0},
      }};

      vector<Edge> result = prims_algo(graph, 5);
      for(auto i:result){
      cout<<"EDGE [ " <<i.first.first<<", "<<i.first.second<<"], length: "<<i.second<<endl;
      }

      return 0;
      }









      share|improve this question















      Could anyone comment on what could be done better and if I made any mistakes?



      #include <iostream>
      #include <vector>
      #include <algorithm>


      using namespace std;

      typedef pair<pair<int, int>, int> Edge; //a, b, length
      // A---------B
      // length


      vector<Edge> prims_algo(vector<vector<int>> graph, int number_of_nodes){
      vector<int> unvisited;
      vector<int> visited;
      vector<Edge> result;

      //mark first as visited and mark the rest as unvisited
      for (int i = 1; i < number_of_nodes; i++)
      unvisited.push_back(i);
      visited.push_back(0);

      while (!unvisited.empty()) {

      vector<Edge> edges_with_lengths;
      //put all edges (with their lengths) from nodes that are in visited
      for(auto node : visited) {
      for (int sec_node = 0; sec_node < number_of_nodes; sec_node++) {
      if (graph[node][sec_node] > 0 && find(unvisited.begin(), unvisited.end(), sec_node) != unvisited.end()) {
      //add if there is connection and second node is not visited yet
      Edge e = make_pair(make_pair(node, sec_node), graph[node][sec_node]);
      edges_with_lengths.push_back(e);
      }
      }
      }

      //find the shortest edge
      pair<pair<int, int>, int> the_shortest;
      the_shortest = edges_with_lengths.front();
      for(auto i: edges_with_lengths){
      if(the_shortest.second > i.second)
      the_shortest = i;
      }

      //add the shortest path to the result
      result.push_back(the_shortest);

      //remove a node that the shortest edge leads to
      unvisited.erase(remove(unvisited.begin(), unvisited.end(), the_shortest.first.second), unvisited.end());

      //mark this node as visited
      visited.push_back(the_shortest.first.second);
      };
      return result;
      }


      int main() {
      /*
      2 3
      (0)--(1)--(2)
      | / |
      6| 8/ 5 |7
      | / |
      (3)-------(4)
      9 */
      vector<vector<int>> graph =
      {{{0, 2, 0, 6, 0},
      {2, 0, 3, 8, 5},
      {0, 3, 0, 0, 7},
      {6, 8, 0, 0, 9},
      {0, 5, 7, 9, 0},
      }};

      vector<Edge> result = prims_algo(graph, 5);
      for(auto i:result){
      cout<<"EDGE [ " <<i.first.first<<", "<<i.first.second<<"], length: "<<i.second<<endl;
      }

      return 0;
      }






      c++ algorithm graph






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 25 '16 at 10:01









      Jamal

      30.2k11116226




      30.2k11116226










      asked Apr 25 '16 at 7:36









      Mateusz

      15919




      15919






















          2 Answers
          2






          active

          oldest

          votes


















          3














          Code looks OK.



          I would suggest you to do some class instead of Edge:



          //typedef pair<pair<int, int>, int> Edge; //a, b, length
          struct Edge{
          int a;
          int b;
          int length;
          };


          Also I suggest to have some predefined type for vector<Edge>



          using EdgeContainer = vector<Edge>;


          You have duplication near //find the shortest edge, you probably need Edge there



          Here the_shortest is probably not initialized. Also you probably might use something from <algorithm> (but I will do it in same way as you).



              //find the shortest edge
          pair<pair<int, int>, int> the_shortest;
          the_shortest = edges_with_lengths.front();
          for(auto i: edges_with_lengths){
          if(the_shortest.second > i.second)
          the_shortest = i;
          }


          Another probably micro optimization would be to write ++i in loops:



          //for (int i = 1; i < number_of_nodes; i++)
          for (int i = 1; i < number_of_nodes; ++i){
          // ...
          }


          Also in C++11 main() does not need to return 0;.






          share|improve this answer

















          • 1




            "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
            – scottbb
            Apr 25 '16 at 12:29










          • fully agree, but i think is good habit to use it as ++i
            – Nick
            Apr 25 '16 at 17:42










          • Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
            – scottbb
            Apr 25 '16 at 18:06



















          0














          you have not used priority queue so performance is bad





          share








          New contributor




          sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.


















            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f126617%2fimplementation-of-prims-algorithm-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3














            Code looks OK.



            I would suggest you to do some class instead of Edge:



            //typedef pair<pair<int, int>, int> Edge; //a, b, length
            struct Edge{
            int a;
            int b;
            int length;
            };


            Also I suggest to have some predefined type for vector<Edge>



            using EdgeContainer = vector<Edge>;


            You have duplication near //find the shortest edge, you probably need Edge there



            Here the_shortest is probably not initialized. Also you probably might use something from <algorithm> (but I will do it in same way as you).



                //find the shortest edge
            pair<pair<int, int>, int> the_shortest;
            the_shortest = edges_with_lengths.front();
            for(auto i: edges_with_lengths){
            if(the_shortest.second > i.second)
            the_shortest = i;
            }


            Another probably micro optimization would be to write ++i in loops:



            //for (int i = 1; i < number_of_nodes; i++)
            for (int i = 1; i < number_of_nodes; ++i){
            // ...
            }


            Also in C++11 main() does not need to return 0;.






            share|improve this answer

















            • 1




              "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
              – scottbb
              Apr 25 '16 at 12:29










            • fully agree, but i think is good habit to use it as ++i
              – Nick
              Apr 25 '16 at 17:42










            • Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
              – scottbb
              Apr 25 '16 at 18:06
















            3














            Code looks OK.



            I would suggest you to do some class instead of Edge:



            //typedef pair<pair<int, int>, int> Edge; //a, b, length
            struct Edge{
            int a;
            int b;
            int length;
            };


            Also I suggest to have some predefined type for vector<Edge>



            using EdgeContainer = vector<Edge>;


            You have duplication near //find the shortest edge, you probably need Edge there



            Here the_shortest is probably not initialized. Also you probably might use something from <algorithm> (but I will do it in same way as you).



                //find the shortest edge
            pair<pair<int, int>, int> the_shortest;
            the_shortest = edges_with_lengths.front();
            for(auto i: edges_with_lengths){
            if(the_shortest.second > i.second)
            the_shortest = i;
            }


            Another probably micro optimization would be to write ++i in loops:



            //for (int i = 1; i < number_of_nodes; i++)
            for (int i = 1; i < number_of_nodes; ++i){
            // ...
            }


            Also in C++11 main() does not need to return 0;.






            share|improve this answer

















            • 1




              "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
              – scottbb
              Apr 25 '16 at 12:29










            • fully agree, but i think is good habit to use it as ++i
              – Nick
              Apr 25 '16 at 17:42










            • Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
              – scottbb
              Apr 25 '16 at 18:06














            3












            3








            3






            Code looks OK.



            I would suggest you to do some class instead of Edge:



            //typedef pair<pair<int, int>, int> Edge; //a, b, length
            struct Edge{
            int a;
            int b;
            int length;
            };


            Also I suggest to have some predefined type for vector<Edge>



            using EdgeContainer = vector<Edge>;


            You have duplication near //find the shortest edge, you probably need Edge there



            Here the_shortest is probably not initialized. Also you probably might use something from <algorithm> (but I will do it in same way as you).



                //find the shortest edge
            pair<pair<int, int>, int> the_shortest;
            the_shortest = edges_with_lengths.front();
            for(auto i: edges_with_lengths){
            if(the_shortest.second > i.second)
            the_shortest = i;
            }


            Another probably micro optimization would be to write ++i in loops:



            //for (int i = 1; i < number_of_nodes; i++)
            for (int i = 1; i < number_of_nodes; ++i){
            // ...
            }


            Also in C++11 main() does not need to return 0;.






            share|improve this answer












            Code looks OK.



            I would suggest you to do some class instead of Edge:



            //typedef pair<pair<int, int>, int> Edge; //a, b, length
            struct Edge{
            int a;
            int b;
            int length;
            };


            Also I suggest to have some predefined type for vector<Edge>



            using EdgeContainer = vector<Edge>;


            You have duplication near //find the shortest edge, you probably need Edge there



            Here the_shortest is probably not initialized. Also you probably might use something from <algorithm> (but I will do it in same way as you).



                //find the shortest edge
            pair<pair<int, int>, int> the_shortest;
            the_shortest = edges_with_lengths.front();
            for(auto i: edges_with_lengths){
            if(the_shortest.second > i.second)
            the_shortest = i;
            }


            Another probably micro optimization would be to write ++i in loops:



            //for (int i = 1; i < number_of_nodes; i++)
            for (int i = 1; i < number_of_nodes; ++i){
            // ...
            }


            Also in C++11 main() does not need to return 0;.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Apr 25 '16 at 11:31









            Nick

            667413




            667413








            • 1




              "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
              – scottbb
              Apr 25 '16 at 12:29










            • fully agree, but i think is good habit to use it as ++i
              – Nick
              Apr 25 '16 at 17:42










            • Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
              – scottbb
              Apr 25 '16 at 18:06














            • 1




              "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
              – scottbb
              Apr 25 '16 at 12:29










            • fully agree, but i think is good habit to use it as ++i
              – Nick
              Apr 25 '16 at 17:42










            • Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
              – scottbb
              Apr 25 '16 at 18:06








            1




            1




            "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
            – scottbb
            Apr 25 '16 at 12:29




            "Another probably micro optimization would be to write ++i in loops" For this case (integer or other primitive type), there is no optimization gain at all. For user-defined types, you are correct: postincrement involves a copy to be made, whereas preincrement doesn't. So prefer ++i for user-defined types, and then continue to use it for primitive data types if the choice between pre- vs post- increment doesn't matter, for code consistency.
            – scottbb
            Apr 25 '16 at 12:29












            fully agree, but i think is good habit to use it as ++i
            – Nick
            Apr 25 '16 at 17:42




            fully agree, but i think is good habit to use it as ++i
            – Nick
            Apr 25 '16 at 17:42












            Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
            – scottbb
            Apr 25 '16 at 18:06




            Agreed, hence the last part of my comment, "continue to use it for primitive data types ... for code consistency"
            – scottbb
            Apr 25 '16 at 18:06













            0














            you have not used priority queue so performance is bad





            share








            New contributor




            sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.























              0














              you have not used priority queue so performance is bad





              share








              New contributor




              sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.





















                0












                0








                0






                you have not used priority queue so performance is bad





                share








                New contributor




                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.









                you have not used priority queue so performance is bad






                share








                New contributor




                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.








                share


                share






                New contributor




                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.









                answered 2 mins ago









                sukumar

                1




                1




                New contributor




                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.





                New contributor





                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.






                sukumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f126617%2fimplementation-of-prims-algorithm-in-c%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Ottavio Pratesi

                    Tricia Helfer

                    15 giugno