【问题标题】:C++: priority queue with pointer to object does not work correctlyC ++:具有指向对象的指针的优先级队列无法正常工作
【发布时间】:2016-06-30 21:19:21
【问题描述】:

我正在尝试实现 Dijkstra 算法。为此,我使用了一个优先级队列,该队列存储指向“节点”类对象的指针,该队列应返回与起始节点距离最短的节点。我减少了我的代码,以便它手动编辑开始节点和当前节点之间的距离并从优先级队列中提取元素。通常 Dijkstra 会这样做。以下代码无法正常工作:

using namespace std;

#include <iostream>
#include <limits>
#include <vector>
#include <queue>

const int numberNodes = 6;
int IMAX = numeric_limits<int>::max();

class Node{
public:
    Node(float pdistance, int pid){distance = pdistance;    id = pid;}
    float distance;
    int id;     //only for debug
};

Node** nodes;       //in int main() Array of Node*

class Compare{  //Compare pointer to nodes based on distance to start node (Dijkstra)
public:
    bool operator() (Node *n1, Node *n2) const {
        return n1->distance>n2->distance;
    }
};

priority_queue<Node*, vector<Node*>, Compare> pq;

int main(){
    nodes = new Node*[numberNodes];
    for(int i=0; i<numberNodes; i++){       //create new objects and store them in pq
        nodes[i] = new Node(IMAX, i);
        pq.push(nodes[i]);
    }
    Node* sNode;        //Start node. not contained in nodes[]
    sNode = new Node(0, -1);        //distance 0, id -1
    pq.push(sNode);

    cout << "extracted: Node " << (pq.top())->id << " , distance " << (pq.top())->distance << endl;
    pq.pop();

    nodes[0]->distance = 0.5;
    nodes[1]->distance = 0.5;
    cout << "extracted: Node " << (pq.top())->id << " , distance " << (pq.top())->distance << endl;
    pq.pop();       

    cout << "extracted: Node " << (pq.top())->id << " , distance " << (pq.top())->distance << endl;
    pq.pop();   

    nodes[2]->distance = 2.5;
    nodes[3]->distance = 3.5;
    cout << "extracted: Node " << (pq.top())->id << " , distance " << (pq.top())->distance << endl;
    pq.pop();   
}

返回:

extracted: Node -1 , distance 0
extracted: Node 0 , distance 0.5
extracted: Node 1 , distance 0.5
extracted: Node 5 , distance 2.14748e+09

pq 正常工作三次,但最后它应该返回距离为 2.5 的节点 2。

那么我怎样才能让它工作呢?

感谢解答

【问题讨论】:

    标签: c++ oop pointers stl


    【解决方案1】:

    由于您要弹出priority_queue 的元素,因此它的大小正在减小,因为行:

    节点[2]->距离 = 2.5; 节点[3]->距离 = 3.5;

    应改为:

    节点[0]->距离 = 2.5; 节点[1]->距离 = 3.5;

    【讨论】:

    • pq的大小减小了,但是元素按照sNode、nodes[0]、nodes[1]的顺序弹出。节点[2] - 节点[5] 仍然包含在 pq 中。当设置nodes[3]->distance = 3.5时nodes[1]已经从pq中弹出了。
    • 是的,你是对的。当您插入 sNode 元素时,您的 priority_queue 正在重新排序,因此您在节点中的引用不正确。我建议在你的 pq 中插入所有元素,设置距离值而不是 IMAX,或者使用另一个 STL 容器,如堆。看这里 [stackoverflow.com/a/18493336/6535516]
    【解决方案2】:

    在顶部,变量 numberNodes 设置为等于 6。 将其减少到一个较小的数字,因为它在您的主函数中初始化 6 个节点。

    这个巨大的数字是编译器初始化浮点数的默认垃圾,因为你声明它但没有分配任何东西。

    为避免此问题,请确保在使用之前初始化所有变量。

    for(int i=0; i<numberNodes; i++){       //create new objects and store them in pq
        nodes[i] = new Node(IMAX, i);
        nodes[i].distance = 0.0f; //<--set a default value
        pq.push(nodes[i]);
    }
    

    【讨论】:

    • 我在构造函数的调用中初始化了距离,所以我应该给它分配一些东西。在开始时,除了起始节点之外的所有节点的距离应该是无限的。 (顺便说一句,nodes[i] 是一个指向 Node 的指针,所以它应该是 nodes[i]->distance。)第一句话是什么意思?我无法减少 numberNodes,因为它是 const int。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多