Djikstra implementation for large graphs

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












I am implementing the Djikstra algorithm for a large graph (40k nodes, 100k arcs). For shorter paths the searchtime is under a second for larger ones (from one end to the other) it take quite some minutes to do it. I am also drawing the path after the search, so I am using some Qt objects. How could I make it faster? I feel like I am losing time when I search the neighbors because of the map structure.



this is the class



class PathFinder 
public:
void findPath2(const Node & start, Node & finish);

static PathFinder& getInstance();
PathFinder();
PathFinder(Gps gps);
~PathFinder();

unsigned int* getPrev() const;
void setPrev(unsigned int* prev);
QVector<unsigned int> makePath(int target);

GraphicNode* getTo();
GraphicNode* getFrom();

void setTo(GraphicNode* node);
void setFrom(GraphicNode* node);

class Compare

public:
bool operator() (std::pair<Node*, int> a, std::pair<Node*, int> b)

return a.second > b.second;

;


private:
static PathFinder* _pathfinder;
Gps _gps;
GraphicNode* _from;
GraphicNode* _to;

unsigned int* _prev;
unsigned int* _dist;
unsigned int _notVisited;

bool selectedNode = false;


Node* getMinNode();
bool hasNotVisited();
;


this is the search function



void PathFinder::findPath2(const Node& start, Node& finish)

QVector<Node> nodes=_gps.graph().nodes();

std::priority_queue<std::pair<Node*,int>,std::vector<std::pair<Node*, int>>,Compare> q;

_dist[start.id()] = 0;
for (int i = 0; i < nodes.size(); i++)
std::pair<Node*, int> p = std::make_pair(const_cast<Node*>(&nodes.at(i)), _dist[i]);
q.push(p);


while (!q.empty())
std::pair<Node*, int> top = q.top();
q.pop();
Node* minNode = top.first;
QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();

if (*minNode == finish)
return;

int minNodeId = minNode->id();
for (QMap<Node*, unsigned short>::iterator iterator=nextNodes.begin(); iterator != nextNodes.end(); iterator++)
Node* nextNode = iterator.key();
int altDist = _dist[minNodeId] + nextNodes.value(nextNode);
int nextNodeId = nextNode->id();
if (altDist < _dist[nextNodeId])
_dist[nextNodeId] = altDist;
_prev[nextNodeId] = minNodeId;
std::pair<Node*, int> p = std::make_pair(nextNode, _dist[nextNodeId]);
q.push(p);






this is the structure of the node, it contains a map to its neighbors with the weight as the value, x and y are coordinates for drawing it later on, don't mind that



class Node 
private:
unsigned short _id;
double _y;
double _x;
QMap<Node*, unsigned short> _nextNodes;
bool _visited = false;


public:
Node();
Node(unsigned short id, double longitude, double latitude);

unsigned short id() const;
double y() const;
void setY(double y);
double x() const;
void setX(double x);

bool operator==(const Node& other);
void addNextNode(Node* node, unsigned short length);

QMap<Node*, unsigned short> nextNodes() const;
;






share|improve this question





















  • Have you tried using std::vectorover QVector (and so on)?
    – JVApen
    Apr 15 at 10:23
















up vote
2
down vote

favorite












I am implementing the Djikstra algorithm for a large graph (40k nodes, 100k arcs). For shorter paths the searchtime is under a second for larger ones (from one end to the other) it take quite some minutes to do it. I am also drawing the path after the search, so I am using some Qt objects. How could I make it faster? I feel like I am losing time when I search the neighbors because of the map structure.



this is the class



class PathFinder 
public:
void findPath2(const Node & start, Node & finish);

static PathFinder& getInstance();
PathFinder();
PathFinder(Gps gps);
~PathFinder();

unsigned int* getPrev() const;
void setPrev(unsigned int* prev);
QVector<unsigned int> makePath(int target);

GraphicNode* getTo();
GraphicNode* getFrom();

void setTo(GraphicNode* node);
void setFrom(GraphicNode* node);

class Compare

public:
bool operator() (std::pair<Node*, int> a, std::pair<Node*, int> b)

return a.second > b.second;

;


private:
static PathFinder* _pathfinder;
Gps _gps;
GraphicNode* _from;
GraphicNode* _to;

unsigned int* _prev;
unsigned int* _dist;
unsigned int _notVisited;

bool selectedNode = false;


Node* getMinNode();
bool hasNotVisited();
;


this is the search function



void PathFinder::findPath2(const Node& start, Node& finish)

QVector<Node> nodes=_gps.graph().nodes();

std::priority_queue<std::pair<Node*,int>,std::vector<std::pair<Node*, int>>,Compare> q;

_dist[start.id()] = 0;
for (int i = 0; i < nodes.size(); i++)
std::pair<Node*, int> p = std::make_pair(const_cast<Node*>(&nodes.at(i)), _dist[i]);
q.push(p);


while (!q.empty())
std::pair<Node*, int> top = q.top();
q.pop();
Node* minNode = top.first;
QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();

if (*minNode == finish)
return;

int minNodeId = minNode->id();
for (QMap<Node*, unsigned short>::iterator iterator=nextNodes.begin(); iterator != nextNodes.end(); iterator++)
Node* nextNode = iterator.key();
int altDist = _dist[minNodeId] + nextNodes.value(nextNode);
int nextNodeId = nextNode->id();
if (altDist < _dist[nextNodeId])
_dist[nextNodeId] = altDist;
_prev[nextNodeId] = minNodeId;
std::pair<Node*, int> p = std::make_pair(nextNode, _dist[nextNodeId]);
q.push(p);






this is the structure of the node, it contains a map to its neighbors with the weight as the value, x and y are coordinates for drawing it later on, don't mind that



class Node 
private:
unsigned short _id;
double _y;
double _x;
QMap<Node*, unsigned short> _nextNodes;
bool _visited = false;


public:
Node();
Node(unsigned short id, double longitude, double latitude);

unsigned short id() const;
double y() const;
void setY(double y);
double x() const;
void setX(double x);

bool operator==(const Node& other);
void addNextNode(Node* node, unsigned short length);

QMap<Node*, unsigned short> nextNodes() const;
;






share|improve this question





















  • Have you tried using std::vectorover QVector (and so on)?
    – JVApen
    Apr 15 at 10:23












up vote
2
down vote

favorite









up vote
2
down vote

favorite











I am implementing the Djikstra algorithm for a large graph (40k nodes, 100k arcs). For shorter paths the searchtime is under a second for larger ones (from one end to the other) it take quite some minutes to do it. I am also drawing the path after the search, so I am using some Qt objects. How could I make it faster? I feel like I am losing time when I search the neighbors because of the map structure.



this is the class



class PathFinder 
public:
void findPath2(const Node & start, Node & finish);

static PathFinder& getInstance();
PathFinder();
PathFinder(Gps gps);
~PathFinder();

unsigned int* getPrev() const;
void setPrev(unsigned int* prev);
QVector<unsigned int> makePath(int target);

GraphicNode* getTo();
GraphicNode* getFrom();

void setTo(GraphicNode* node);
void setFrom(GraphicNode* node);

class Compare

public:
bool operator() (std::pair<Node*, int> a, std::pair<Node*, int> b)

return a.second > b.second;

;


private:
static PathFinder* _pathfinder;
Gps _gps;
GraphicNode* _from;
GraphicNode* _to;

unsigned int* _prev;
unsigned int* _dist;
unsigned int _notVisited;

bool selectedNode = false;


Node* getMinNode();
bool hasNotVisited();
;


this is the search function



void PathFinder::findPath2(const Node& start, Node& finish)

QVector<Node> nodes=_gps.graph().nodes();

std::priority_queue<std::pair<Node*,int>,std::vector<std::pair<Node*, int>>,Compare> q;

_dist[start.id()] = 0;
for (int i = 0; i < nodes.size(); i++)
std::pair<Node*, int> p = std::make_pair(const_cast<Node*>(&nodes.at(i)), _dist[i]);
q.push(p);


while (!q.empty())
std::pair<Node*, int> top = q.top();
q.pop();
Node* minNode = top.first;
QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();

if (*minNode == finish)
return;

int minNodeId = minNode->id();
for (QMap<Node*, unsigned short>::iterator iterator=nextNodes.begin(); iterator != nextNodes.end(); iterator++)
Node* nextNode = iterator.key();
int altDist = _dist[minNodeId] + nextNodes.value(nextNode);
int nextNodeId = nextNode->id();
if (altDist < _dist[nextNodeId])
_dist[nextNodeId] = altDist;
_prev[nextNodeId] = minNodeId;
std::pair<Node*, int> p = std::make_pair(nextNode, _dist[nextNodeId]);
q.push(p);






this is the structure of the node, it contains a map to its neighbors with the weight as the value, x and y are coordinates for drawing it later on, don't mind that



class Node 
private:
unsigned short _id;
double _y;
double _x;
QMap<Node*, unsigned short> _nextNodes;
bool _visited = false;


public:
Node();
Node(unsigned short id, double longitude, double latitude);

unsigned short id() const;
double y() const;
void setY(double y);
double x() const;
void setX(double x);

bool operator==(const Node& other);
void addNextNode(Node* node, unsigned short length);

QMap<Node*, unsigned short> nextNodes() const;
;






share|improve this question













I am implementing the Djikstra algorithm for a large graph (40k nodes, 100k arcs). For shorter paths the searchtime is under a second for larger ones (from one end to the other) it take quite some minutes to do it. I am also drawing the path after the search, so I am using some Qt objects. How could I make it faster? I feel like I am losing time when I search the neighbors because of the map structure.



this is the class



class PathFinder 
public:
void findPath2(const Node & start, Node & finish);

static PathFinder& getInstance();
PathFinder();
PathFinder(Gps gps);
~PathFinder();

unsigned int* getPrev() const;
void setPrev(unsigned int* prev);
QVector<unsigned int> makePath(int target);

GraphicNode* getTo();
GraphicNode* getFrom();

void setTo(GraphicNode* node);
void setFrom(GraphicNode* node);

class Compare

public:
bool operator() (std::pair<Node*, int> a, std::pair<Node*, int> b)

return a.second > b.second;

;


private:
static PathFinder* _pathfinder;
Gps _gps;
GraphicNode* _from;
GraphicNode* _to;

unsigned int* _prev;
unsigned int* _dist;
unsigned int _notVisited;

bool selectedNode = false;


Node* getMinNode();
bool hasNotVisited();
;


this is the search function



void PathFinder::findPath2(const Node& start, Node& finish)

QVector<Node> nodes=_gps.graph().nodes();

std::priority_queue<std::pair<Node*,int>,std::vector<std::pair<Node*, int>>,Compare> q;

_dist[start.id()] = 0;
for (int i = 0; i < nodes.size(); i++)
std::pair<Node*, int> p = std::make_pair(const_cast<Node*>(&nodes.at(i)), _dist[i]);
q.push(p);


while (!q.empty())
std::pair<Node*, int> top = q.top();
q.pop();
Node* minNode = top.first;
QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();

if (*minNode == finish)
return;

int minNodeId = minNode->id();
for (QMap<Node*, unsigned short>::iterator iterator=nextNodes.begin(); iterator != nextNodes.end(); iterator++)
Node* nextNode = iterator.key();
int altDist = _dist[minNodeId] + nextNodes.value(nextNode);
int nextNodeId = nextNode->id();
if (altDist < _dist[nextNodeId])
_dist[nextNodeId] = altDist;
_prev[nextNodeId] = minNodeId;
std::pair<Node*, int> p = std::make_pair(nextNode, _dist[nextNodeId]);
q.push(p);






this is the structure of the node, it contains a map to its neighbors with the weight as the value, x and y are coordinates for drawing it later on, don't mind that



class Node 
private:
unsigned short _id;
double _y;
double _x;
QMap<Node*, unsigned short> _nextNodes;
bool _visited = false;


public:
Node();
Node(unsigned short id, double longitude, double latitude);

unsigned short id() const;
double y() const;
void setY(double y);
double x() const;
void setX(double x);

bool operator==(const Node& other);
void addNextNode(Node* node, unsigned short length);

QMap<Node*, unsigned short> nextNodes() const;
;








share|improve this question












share|improve this question




share|improve this question








edited Apr 15 at 13:21









t3chb0t

32k54195




32k54195









asked Apr 15 at 8:06









rednefed

111




111











  • Have you tried using std::vectorover QVector (and so on)?
    – JVApen
    Apr 15 at 10:23
















  • Have you tried using std::vectorover QVector (and so on)?
    – JVApen
    Apr 15 at 10:23















Have you tried using std::vectorover QVector (and so on)?
– JVApen
Apr 15 at 10:23




Have you tried using std::vectorover QVector (and so on)?
– JVApen
Apr 15 at 10:23










1 Answer
1






active

oldest

votes

















up vote
1
down vote













  1. Don't use QT objects when you are not working with QT constructs. There is no benefit to it.


  2. Your node::_id is unsigned shirt, which for MSVS has a range of 0 to 65,535. Be aware of that when you graph grows.


  3. Do not use a map. A std::vector is way faster/bettter for traversing than a std::map.



  4. You do a lot of copying data around:



    QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();


That is a copy of all neighbors everytime you access a node during your search. If you really need the temporary, which you dont then at least make this a reference.






share|improve this answer





















    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',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    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%2f192099%2fdjikstra-implementation-for-large-graphs%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    1. Don't use QT objects when you are not working with QT constructs. There is no benefit to it.


    2. Your node::_id is unsigned shirt, which for MSVS has a range of 0 to 65,535. Be aware of that when you graph grows.


    3. Do not use a map. A std::vector is way faster/bettter for traversing than a std::map.



    4. You do a lot of copying data around:



      QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();


    That is a copy of all neighbors everytime you access a node during your search. If you really need the temporary, which you dont then at least make this a reference.






    share|improve this answer

























      up vote
      1
      down vote













      1. Don't use QT objects when you are not working with QT constructs. There is no benefit to it.


      2. Your node::_id is unsigned shirt, which for MSVS has a range of 0 to 65,535. Be aware of that when you graph grows.


      3. Do not use a map. A std::vector is way faster/bettter for traversing than a std::map.



      4. You do a lot of copying data around:



        QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();


      That is a copy of all neighbors everytime you access a node during your search. If you really need the temporary, which you dont then at least make this a reference.






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        1. Don't use QT objects when you are not working with QT constructs. There is no benefit to it.


        2. Your node::_id is unsigned shirt, which for MSVS has a range of 0 to 65,535. Be aware of that when you graph grows.


        3. Do not use a map. A std::vector is way faster/bettter for traversing than a std::map.



        4. You do a lot of copying data around:



          QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();


        That is a copy of all neighbors everytime you access a node during your search. If you really need the temporary, which you dont then at least make this a reference.






        share|improve this answer













        1. Don't use QT objects when you are not working with QT constructs. There is no benefit to it.


        2. Your node::_id is unsigned shirt, which for MSVS has a range of 0 to 65,535. Be aware of that when you graph grows.


        3. Do not use a map. A std::vector is way faster/bettter for traversing than a std::map.



        4. You do a lot of copying data around:



          QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();


        That is a copy of all neighbors everytime you access a node during your search. If you really need the temporary, which you dont then at least make this a reference.







        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Apr 15 at 12:38









        miscco

        3,144516




        3,144516






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192099%2fdjikstra-implementation-for-large-graphs%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Greedy Best First Search implementation in Rust

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            C++11 CLH Lock Implementation