C++ C++;使用优先级队列调试断言时失败,表达式:无效堆

C++ C++;使用优先级队列调试断言时失败,表达式:无效堆,c++,priority-queue,assertions,C++,Priority Queue,Assertions,环境: -Win7 pro x64 -VS2010 -C++ -空项目 目标: 使用优先级队列实现Dijkstra最短路径算法 问题: 当程序运行时,它得到一个调试断言失败,表达式:无效堆错误。如果用户将源顶点输入为1,则一切正常。仅当源顶点不是1时,才会发生断言。此外,如果忽略断言,代码最终将完成并通过图形输出正确的路径。我猜这个错误与更改优先级队列中指针指向的数据有关,但如果是这种情况,我不明白为什么使用1作为源代码可以成功完成代码 谢谢你的帮助 标题: #ifndef _GRAPH_H_

环境:
-Win7 pro x64
-VS2010
-C++
-空项目

目标: 使用优先级队列实现Dijkstra最短路径算法

问题: 当程序运行时,它得到一个调试断言失败,表达式:无效堆错误。如果用户将源顶点输入为1,则一切正常。仅当源顶点不是1时,才会发生断言。此外,如果忽略断言,代码最终将完成并通过图形输出正确的路径。我猜这个错误与更改优先级队列中指针指向的数据有关,但如果是这种情况,我不明白为什么使用1作为源代码可以成功完成代码

谢谢你的帮助

标题:

#ifndef _GRAPH_H_
#define _GRAPH_H_
#include <map>
#include <queue>
#include <vector>
#include <fstream>

using namespace std;

class Graph
{

public:

    struct Vertex
    {
        int name; // V number
        double dv; // distance
        Vertex* pv; // previous V* from this V
        map<Vertex*, double> neighbors; // map of all neighbors/distances connected to vert
    };

    vector<Vertex*> verts; // vector of all V*

    void dijkstra(ifstream& stream, int start_vert); // create graph & find shortest paths
    void printPath(Vertex* v); // echo path

    class CompareVert // overloaded compare operator for priorty queue data struct, sort queue so V with smallest dist on top
    {
    public:
        bool operator()(const Vertex* v1, const Vertex* v2) const
        {
            return v1->dv > v2->dv;
        }
    };
};

#endif

您应该在调用q.top()之后立即从priority_队列中弹出top元素。而是在使用
q.push(it->first)将新元素推入队列后执行q.pop()


在我看来,这并不是您想要的,因为您现在可能会弹出一个与您认为的顶级元素不同的元素

您可能正在推送距离为
无限的
顶点
实例。比较两个
无限
距离将不会产生一个比另一个小的距离,从而使比较器无效

如果这是一个严格的学习练习,并且您实际上不需要
double
距离,我建议您使用整数距离,并使用“大”数代替
infinite


使用
N
位整数使用
2^(N-3)
作为
infinite
值是一个好主意,因为将它们相加将产生
2^(N-2)
,它仍然可以用有符号的N位整数(不是
2^(N-1)
)表示,并且它的值比简单的
infinite
大,也就是说,
infinite+infinite>infinite
,这样可以保持您的顺序正常。

您应该避免修改当前在优先级队列中的元素,至少不要以修改其优先级的方式进行修改。 顶点的优先级由
CompareVert
给出,它取决于
dv
的值。 在“查找路径部分”中

if((temp->dv+it->second)first->dv)
{
打印=假;
it->first->dv=(temp->dv+it->second);//first->pv=temp;
q、 推(它->第一);
}

dv
的赋值会影响队列中当前的元素。当您调用q.push()时,队列意识到它处于无效状态并抱怨

您是否尝试在调试器中单步执行代码?我尝试过。似乎是push_堆调用导致了它。你的意思是
push_back
?@Oli,实际上是push_back,但更准确地说,当我进入代码时,优先级队列从“算法”include使用的是push_堆调用。在将q.top()分配给temp之后,我尝试将代码更改为q.pop()。不幸的是,错误仍然会发生,更糟糕的是,无论选择哪个顶点作为源,错误都会发生,包括1。从算法上讲,将pop()放在top()之后是正确的做法,尽管它不能解决问题。也许你有一些未初始化的东西。我会试着在你的优先队列中注释掉一些东西,看看会发生什么。第一件事是注释掉顶点结构中的映射。你的结构顶点只是有一堆数据成员,这就是为什么我立即怀疑某些东西没有正确初始化的原因。
#include "Graph.h"
#include <iostream>
#include <queue>
#include <limits> // used for numeric_limits<double>::infinity()
#include <vector>

using namespace std;

int path_length = 0;

void Graph::printPath(Vertex* v) // print shortest paths
{
    if (v->pv != NULL)
    {
        printPath(v->pv);
        cout << " -> ";
    }
    cout << v->name;
}

void Graph::dijkstra(ifstream& stream, int start_vert) // create graph & get shortest path
{
    /////////////////////////////////////////////
    /////////////// create graph ////////////////
    /////////////////////////////////////////////

    int total_edges;
    priority_queue<Vertex*, vector<Vertex*>, CompareVert> q;
    double infinity = numeric_limits<double>::infinity();
    int source;
    int dest;
    double dist;
    stream >> total_edges;
    for (int i=0;i<total_edges;i++)
    {
        stream >> source;
        stream >> dest;
        stream >> dist;
        bool source_exists = false;
        bool dest_exists = false;
        Vertex* _source;
        Vertex* _dest;

        for (int i=0;i<verts.size();i++)
        {
            if (verts.at(i)->name == source) // vertex already exists, set to V
            {
                _source = verts.at(i);
                source_exists = true;
                break;
            }
        }

        for (int i=0;i<verts.size();i++)
        {
            if (verts.at(i)->name == dest) // vertex already exists, set to V
            {
                _dest = verts.at(i);
                dest_exists = true;
                break;
            }
        }

        if (!source_exists) // create vert
        {
            _source = new Vertex;
            _source->name = source;
            _source->dv = infinity;
            _source->pv = NULL;
            verts.push_back(_source);
        }

        if (!dest_exists) // create vert
        {
            _dest = new Vertex;
            _dest->name = dest;
            _dest->dv = infinity;
            _dest->pv = NULL;
            verts.push_back(_dest);
        }
        _source->neighbors.insert(pair<Vertex*, double>(_dest, dist)); // populate V's adjacency map
    }

    for (int i=0;i<verts.size();i++)
    {
        if (verts.at(i)->name == start_vert) // set source
        {
            verts.at(i)->dv = 0;
        }       
        q.push(verts.at(i)); // push all vertices to priority queue
    }

    /////////////////////////////////////////////
    ////////////////  find paths  ///////////////
    /////////////////////////////////////////////

    vector<int> displayed;
    bool print; // flag to call printPath
    while (!q.empty())
    {
        map<Vertex*, double>::iterator it;
        Vertex* temp = q.top(); // get V with smallest dist
        print = true;
        for (it = temp->neighbors.begin(); it!=temp->neighbors.end();++it)
        {
            if ((temp->dv + it->second) < it->first->dv)
            {
                print = false;
                it->first->dv = (temp->dv + it->second);
                it->first->pv = temp;
                q.push(it->first);
            }
        }

        for (int i=0;i<displayed.size();i++) // if end V of path has already been printed, do not print
        {
            if (displayed.at(i) == temp->name)
                print = false;
        }

        if (print == true)
        {
            printPath(temp);
            path_length = temp->dv;
            cout << " total distance = " << path_length <<endl << endl;
            displayed.push_back(temp->name);
        }

        path_length = 0;
        q.pop();
    }
}
#include "Graph.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
#include <list>

using namespace std;

string fname;
int vname;
string line;

int main(void)
{
    cout << "Please enter the file to read in a graph (graph.txt): ";
    cin >> fname;
    cout << "Please choose a starting vertex (1 is a good choice): ";
    cin >> vname;
    cout << endl;

    ifstream my_stream (fname);
    Graph my_graph;
    my_graph.dijkstra(my_stream, vname);
    my_stream.close();
}
12
1 2 2
1 4 1
2 4 3
2 5 10
3 1 4
3 6 5
4 3 2
4 5 2
4 6 8
4 7 4
5 7 6
7 6 1
 if ((temp->dv + it->second) < it->first->dv)
 {
     print = false;
     it->first->dv = (temp->dv + it->second);   // <-- here is the problem!
     it->first->pv = temp;
     q.push(it->first);
  }