Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;使Djikstra实现更快_C++_Algorithm_Qt_Search_Graph - Fatal编程技术网

C++ C++;使Djikstra实现更快

C++ C++;使Djikstra实现更快,c++,algorithm,qt,search,graph,C++,Algorithm,Qt,Search,Graph,我正在为一个大型图(40k个节点,100k个弧)实现Djikstra算法。对于较短的路径,搜索时间不到一秒钟;对于较大的路径(从一端到另一端),搜索时间需要几分钟。我还在搜索后绘制路径,所以我使用了一些Qt对象。我怎样才能使它更快?由于地图结构的原因,我觉得我在搜索邻居时正在浪费时间 这是一节课 class PathFinder { public: void findPath2(const Node & start, Node & finish); static P

我正在为一个大型图(40k个节点,100k个弧)实现Djikstra算法。对于较短的路径,搜索时间不到一秒钟;对于较大的路径(从一端到另一端),搜索时间需要几分钟。我还在搜索后绘制路径,所以我使用了一些Qt对象。我怎样才能使它更快?由于地图结构的原因,我觉得我在搜索邻居时正在浪费时间

这是一节课

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();
};
类探路者{
公众:
void findPath2(常量节点和开始、节点和完成);
静态PathFinder&getInstance();
探路者();
探路者(Gps);
~PathFinder();
无符号int*getPrev()常量;
void setPrev(无符号整数*prev);
QVector生成路径(int目标);
GraphicNode*getTo();
GraphicNode*getFrom();
void setTo(GraphicNode*节点);
void setFrom(GraphicNode*节点);
班级比较
{
公众:
布尔运算符()(标准::对a,标准::对b)
{
返回a.second>b.second;
}
};
私人:
静态探路者*_探路者;
全球定位系统;
GraphicNode*\u来自;
图形节点*_至;
无符号整数*_prev;
无符号整数*距离;
未签名整数(未访问);;
bool selectedNode=false;
节点*getMinNode();
布尔没有到访();
};
这是搜索功能

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);
         }
      }
   }
}
void PathFinder::findPath2(常量节点&开始、节点&完成)
{
QVector节点=_gps.graph().nodes();
std::优先级队列q;
_dist[start.id()]=0;
对于(int i=0;inextNodes();
如果(*minNode==完成){
返回;
}
int minNodeId=minNode->id();
for(QMap::iterator iterator=nextNodes.begin();iterator!=nextNodes.end();iterator++){
Node*nextNode=iterator.key();
int altDist=_dist[minNodeId]+nextNodes.value(nextNode);
int nextNodeId=nextNode->id();
如果(altDist<\u dist[nextNodeId]){
_dist[nextNodeId]=altDist;
_prev[nextNodeId]=minNodeId;
std::pair p=std::make_pair(nextNode,_dist[nextNodeId]);
q、 推(p);
}
}
}
}
这是节点的结构,它包含一个到它的邻居的映射,权重作为值,x和y是稍后绘制它的坐标,不要介意

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;
};
类节点{
私人:
无符号短id;
双y;
双x;
QMap_nextNodes;
bool_=false;
公众:
Node();
节点(无符号短id、双经度、双纬度);
无符号短id()常量;
双y()常数;
void setY(双y);
双x()常数;
无效集x(双x);
布尔运算符==(常量节点和其他);
void addNextNode(节点*节点,无符号短长度);
QMap nextNodes()常量;
};

如果您的图形从未更改,解决方案是将其切割成更小的图形

  • 计算每个小图边之间的最短距离并存储结果(边1、边2、距离、内部最短路径)
  • 计算两点之间的距离时,在到达“小图形”边缘时使用存储的结果
  • 我相信这就是谷歌地图和其他寻路工具的工作

    缺点是初始成本(如果您的图形确实从未更改,则可以一次性将这些“迷你”最短路径存储到文件或数据库中)。您必须仔细选择小图形的大小,因为访问存储的结果也会有(时间)成本(无论是在大内存映射中还是在数据库中)。必须找到平衡


    如果同一路径搜索经常返回,另一个方法是存储搜索最多的结果。

    如果图形从未更改,解决方案是将其切割成较小的图形

  • 计算每个小图边之间的最短距离并存储结果(边1、边2、距离、内部最短路径)
  • 计算两点之间的距离时,在到达“小图形”边缘时使用存储的结果
  • 我相信这就是谷歌地图和其他寻路工具的工作

    缺点是初始成本(如果您的图形确实从未更改,则可以一次性将这些“迷你”最短路径存储到文件或数据库中)。您必须仔细选择小图形的大小,因为访问存储的结果也会有(时间)成本(无论是在大内存映射中还是在数据库中)。必须找到平衡


    如果同一路径搜索经常返回,另一个想法是存储搜索最多的结果。

    如果使用优先级队列和邻接列表,则实现的复杂性是
    O((E+V)log V)
    。这应该足以在任何合适的CPU上,在您的图形上计算出几毫秒内的任何最短路径

    您似乎正确地完成了优先级队列部分。但是为什么要使用地图而不是邻接列表呢?这似乎太过分了

    您的实现隐藏了一些额外的、不必要的工作:

    QMap<Node*, unsigned short> nextNodes = minNode->nextNodes();
    
    或指针:

    QMap<Node*, unsigned short>* nextNodes = minNode->nextNodes();
    
    QMap*nextNodes=minNode->nextNodes();
    
    单凭这一点就应该大有帮助。之后,我会切换到链表。
    QMap
    是使用红黑树实现的,因此迭代它要比迭代链表慢


    如果您的图形增长得更多,user6106573的建议是非常好的(但对于您当前的图形大小来说,这完全是多余的)。另一个建议可能是选择一条不完全是最短路径的最短路径:*u搜索算法-检查
    有界松弛
    部分。同样,对于您当前的图形大小,这不是必需的。

    如果您使用的是优先级队列和邻接列表,那么您的实现
    QMap<Node*, unsigned short>* nextNodes = minNode->nextNodes();