c++ - vector 问题 (std::out_of_range)

标签 c++ stl vector

这是我的问题的描述:

程序说明:
我正在用 C++ 实现一个程序,该程序测试 Prim 寻找最小生成树的算法。该程序的目标是计算为选定数量的随机图找到最小生成树所需的秒数。

到目前为止我做了什么?
我完成了整个程序的函数和头文件的实现。由于源代码很小,为了清晰起见,我决定将其粘贴到此邮件中,以便更好地可视化问题。

问题:
出于某种原因,我在应用程序运行时遇到了某种“超出范围”的 vector 问题。 该问题已在(“Prim_and_Kruskal_Algorithms.cpp”)文件中标记。

请求帮助:
如果有人能帮助我发现问题,我将不胜感激。我已经用这个问题内联了源代码。

源代码:

(Undirected_Graph.h) 文件:

#ifndef UNDIRECTED_GRAPH_H
#define UNDIRECTED_GRAPH_H

#include <vector>
using std::vector;

#include <climits>

class Edge;

class Node
{
    public:

        Node(int);                 //The constructor.

        int id;                    //For the id of the node.
        bool visited;              //For checking visited nodes.
        int distance;

        vector <Edge*> adj;       //The adjacent nodes.
};

class Edge
{
    public:

        Edge(Node*, Node*, int);   //The constructor.

        Node* start_Node;          //The start_Node start of the edge.
        Node* end_Node;            //The end of the edge.
        int w;                     //The weight of the edge.

        bool isConnected(Node* node1, Node* node2)  //Checks if the nodes are connected.
        {
            return((node1 == this->start_Node && node2 == this->end_Node) ||
                   (node1 == this->end_Node   && node2 == this->start_Node));
        }
};

class Graph
{
    public:

        Graph(int);                    //The Constructor.

        int max_Nodes;                 //Maximum Number of allowed Nodes.

        vector <Edge*> edges_List;     //For storing the edges of the graph.
        vector <Node*> nodes_List;     //For storing the nodes of the graph.

        void insertEdge(int, int, int);

        int getNumNodes();
        int getNumEdges();
};

#endif

(Undirected_Graph.cpp) 文件:

#include "Undirected_Graph.h"

Node::Node(int id_Num)
{
    id = id_Num;
    visited = 0;
    distance = INT_MAX;
}

Edge::Edge(Node* a, Node* b, int weight)
{
    start_Node = a;
    end_Node = b;
    w = weight;
}

Graph::Graph(int size)
{
    max_Nodes = size;

    for (int i = 1; i <= max_Nodes; ++i)
    {
        Node* temp = new Node(i);

        nodes_List.push_back(temp);
    }
}

void Graph::insertEdge(int x, int y, int w)
{
    Node* a = nodes_List[x-1];
    Node* b = nodes_List[y-1];

    Edge* edge1 = new Edge(a, b, w);
    Edge* edge2 = new Edge(b, a, w);

    edges_List.push_back(edge1);

    a->adj.push_back(edge1);
    b->adj.push_back(edge2);
}

int Graph::getNumNodes()
{
    return max_Nodes;
}

int Graph::getNumEdges()
{
    return edges_List.size();
}

(Prim_and_Kruskal_Algorithms.h) 文件:

#ifndef PRIM_AND_KRUSKAL_ALGORITHMS_H
#define PRIM_AND_KRUSKAL_ALGORITHMS_H

class PKA
{
    private:
    //inline void generateRandomGraph();

    protected:
    //-No Protected Data Members in this Class.

    public:
        void runAlgorithms();
        void prim();
};

#endif

(Prim_and_Kruskal_Algorithms.cpp) 文件 *(问题出在这个文件中,并在下面标记):*

#include "Prim_and_Kruskal_Algorithms.h"
#include "Undirected_Graph.h"

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <cstdlib>
using std::rand;
using std::srand;

#include <ctime>
using std::time;

//=============================================================================
//============Global Variables and Settings for the program====================
//=============================================================================

const int numIterations = 1; //How many times the Prim function will run.
const int numNodes = 10;     //The number of nodes in each graph.
const int numEdges = 9;      //The number of edges for each graph.
const int sRandWeight = 1;   //The "start" range of the weight of each edge in the graph.
const int eRandWeight = 100; //The "end" range of the weight of each edge in the graph.

//=============================================================================
//=============================================================================
//=============================================================================

void PKA::runAlgorithms()   //Runs the Algorithms
{
        srand( time(0) );

    cout << "------------------------------" << endl;

        //Calling the Functions:
        cout << "\nRunning the Prim's Algorithms:\nPlease wait till the completion of the execution time" << endl;

        //===============================================

        //Start the clock for Prim's Algorithm:
        clock_t start, finish;
        start = clock();

        for(int iter1 = 1; iter1 <= numIterations; ++iter1)
        {
            prim();
        }

        //Stop the clock for Prim and print the results:
    finish = clock();
        cout << "\n\tThe execution time of Prim's Algorithm:\t" << ((double)(finish - start) / CLOCKS_PER_SEC) << " s";

    return;
}

void PKA::prim()
{
    //=============================================================================
    //=============================Generating A Random Graph=======================
    //=============================================================================

    //Randomizing Values:
    //===============================================

    int randStartNode = rand() % numNodes;     //Generation a random start node.
    int randEndNode = rand() % numNodes;       //Generating a random end node.
    int randWeight;               //Random weight for the edge.

    while(randEndNode == randStartNode)   //Checking if both randomized nodes are equal.
    {
        randEndNode = (rand() % numNodes);
    }

    //===============================================

    Graph myGraph(numNodes);

    for(int i = 0; i < numEdges; ++i)
    {
        //Generating a random weight:
        randWeight =  sRandWeight + rand() % eRandWeight;

        //Inserting a new Edge:
        myGraph.insertEdge(randStartNode, randEndNode, randWeight);
    }


    //=============================================================================
    //=============================================================================
    //=============================================================================

    int currentNode = 0;           //The current Node being under investigation.
    int adjCounter = NULL;         //How many adjacent nodes do we have for the current node.
    int minDistance = NULL;        
    int minIndex = 0;

    myGraph.nodes_List[0]->distance = 0;   //Indicate the start node.
    myGraph.nodes_List[0]->visited = 1;    //The starting node is already considered as a visited node.

    for(int i = 0; i < numNodes - 1; i++)
    {
        //Determine how many adjacent nodes there are for the current node:
        adjCounter = myGraph.nodes_List[currentNode]->adj.size();

        if(adjCounter == 0) //If there are no adjacent nodes to the current node:
        {
            myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;
                    cout << "\n*******Not all nodes are connected!*******" << endl;
            continue;
        }

        minDistance = myGraph.nodes_List[currentNode]->adj.at(0)->w;
        minIndex = 0;

        for(int counter = 0; adjCounter > 0; adjCounter--, counter++)
        {
            if(myGraph.nodes_List[currentNode]->adj[counter]->end_Node->visited == false)
            {
                if(myGraph.nodes_List[currentNode]->distance > myGraph.nodes_List[currentNode]->adj[counter]->w)
                {
                    myGraph.nodes_List[currentNode]->distance = myGraph.nodes_List[currentNode]->adj[counter]->w;
                }

                if(minDistance > myGraph.nodes_List[currentNode]->adj[counter]->w)
                {
                    minDistance = myGraph.nodes_List[currentNode]->adj[counter]->w;
                    minIndex = counter;
                }
            }
        }

                //======================================================================================
                //=========================The Problem is in the following two lines====================
        //======================================================================================

        //Mark the current node as visited:
        myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;

        //Switching to the next node that we have just visited:
        currentNode = myGraph.nodes_List[currentNode]->adj.at(minIndex)->start_Node->id;

        //======================================================================================
        //======================================================================================
        //======================================================================================
    }
}

(Client_Code.cpp) 文件:用于测试程序。

#include "Prim_and_Kruskal_Algorithms.h"
#include <iostream>

using std::cout;
using std::endl;

int main()
{
    cout << "\nWelcome to the Prim and Kruskal Algorithms Comparison!" << endl;
    cout << "\nPlease wait until the completion of the algorithms." << endl;

    PKA myPKA;                //Creating an object of the class.
    myPKA.runAlgorithms();    //Running the Algorithm.

    cout << "\n\nThe program terminated successfully!" << endl;

    return 0;
}

最佳答案

看这一行:

myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;

作为一名经验丰富的 C++ 程序员,我觉得那行代码很可怕。

问题的直接原因是 adj 没有您想象的那么多成员;您要求(在我的测试运行中)大小为零的列表的第 5 个元素。这会让你离开 map ,然后你开始操纵内存。

更一般地说,您不是在检查边界。

更一般地说,您应该允许这些类管理它们自己的成员。使用访问器和修改器(getX()setX(...))以便成员访问全部发生在一个地方,您可以在那里进行边界检查。像那样伸进 myGraph 的喉咙是非常不安全的。

您会注意到,我没有说在何处/何时/如何程序偏离了意图,因此列表没有应有的元素。那是因为我要追查起来太麻烦了。如果您按照我的建议组织类,代码会更清晰,您可以在不同的地方检查您的假设,错误应该会变得很明显。

编辑:
要创建随机连接图,试试这个:

  Graph myGraph(numNodes);              //Create a new Graph.

  // This ensures that the kth node is connected to the [1...(k-1)] subgraph.
  for(int k=2 ; k<=numNodes ; ++k)
    {
      randWeight =  rand() % eRandWeight;
      myGraph.insertEdge(k, rand()%(k-1)+1, randWeight);
    }

  // This adds as many extra links as you want.
  for(int i = 0; i < numExtraEdges; ++i)
    {
      randWeight =  rand() % eRandWeight;
      randStartNode = rand()%(numNodes-1)+1;
      randEndNode = rand()%(numNodes-1)+1;
      myGraph.insertEdge(randStartNode, randEndNode, randWeight);
    }

关于c++ - vector 问题 (std::out_of_range),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5992445/

相关文章:

c++ - 在 2D Vector 字符串中查找重复项

c++ - 带释放的 std::vector<> 的自定义分配器?

c++ - 如何将 "new"数组成员的地址传递给 vector

c++ - 函数式转换语法如何工作?

c++ - std::map:返回由具有相等值的键组成的 vector

c++ - 为什么插入 map<int, int> 失败?

c++ - 在 std::vector 中释放 Mat

c++ - vector 和迭代器的 vector 上的指针

c++ - 如何从 T、T& 或 T* 模板参数中获取 T*

C++ - 检查指针是否指向有效内存(此处不能使用 NULL 检查)