简体   繁体   中英

Indexing vectors in a for loop

This is a follow-up to Returning name of lowest node , only now with more progress and less errors.

Just as last time, this is for a university course, so copy-paste wont exactly be the most beneficial to me, even if it does work.

The problem I am now having relates to the indexing of the vectors in the LeastDistance function, as a runtime exception is generated when the code is run, both in and out of the debugger, with the message that the vector subscript is out of range. If anyone is more familiar with the vector library than me, the relevant line is 1804. This is triggered when accessing the for loop in the same function.

for (int j = 0; j < hnode[i].nodes.size(); j++)

So far, I have written a small helper function, GetIndex, but I am unsure if the code for it is correct, and how to implement it within the LeastDistance function itself. Full code below (apologies for the shoddy formatting, the editor in here was giving me some grief).

#include "stdafx.h"
#include<iostream>
#include<vector>
#define INF = 9999;

using namespace std;

struct Node
{
    char nodeLink;  //adjacent link
    int cost;       //cost of a link
};                  //to use in Dijkstra algorithm


class HeadNode
{
public:
    char Name;
    bool Visited;
    vector<Node> nodes;
    HeadNode(char x) { Name = x; Visited = false; }

};

class Graph
{
    char Start = 'A';
    char StartNode;
    char CurrentNode;
    char Destination;
    int TotalCost = 0;
    vector<HeadNode> hnode;
    vector<char> path;
    vector<int> weight;

public:
    Graph();
    void createHeadNode(char X);
    void createAdjMatrix();
    char LeastDistance(char node);
    void printAdjMatrix();
    void Dijkstra(char StartNode, char Destination);
    void DestinationChangeCaller();
    char GetStartNode();
    int GetIndex(char CurrentNode);
};



int main()
{
    Graph graph;
    graph.createHeadNode('A');
    graph.createHeadNode('B');
    graph.createHeadNode('C');
    graph.createHeadNode('D');
    graph.createHeadNode('E');
    graph.createAdjMatrix();
    graph.GetStartNode();
    graph.DestinationChangeCaller();

    system("pause");
    return 0;
}

void Graph::DestinationChangeCaller()
{
    for (Destination = 'A'; Destination <= 'E'; Destination++)
    {
        Dijkstra(StartNode, Destination);
    }
}



Graph::Graph()
{
}

int Graph::GetIndex(char node)
{
    return(node - 'A');
}

void Graph::createHeadNode(char x)
{
    hnode.push_back(x);
}

char Graph::GetStartNode() // elementary get function with no error correction.
{
    char got;
    cout << "Please enter a node from A-E to start from:  ";
    cin >> got;
    cout << endl;
    return got;
}

void Graph::createAdjMatrix()
{
    hnode[0].nodes.push_back({ 'B', 4 });
    hnode[0].nodes.push_back({ 'C', 1 });
    hnode[1].nodes.push_back({ 'A', 4 });
    hnode[1].nodes.push_back({ 'C', 2 });
    hnode[1].nodes.push_back({ 'D', 1 });
    hnode[2].nodes.push_back({ 'A', 1 });
    hnode[2].nodes.push_back({ 'B', 2 });
    hnode[2].nodes.push_back({ 'D', 3 });
    hnode[2].nodes.push_back({ 'E', 1 });
    hnode[3].nodes.push_back({ 'B', 1 });
    hnode[3].nodes.push_back({ 'C', 3 });
    hnode[3].nodes.push_back({ 'E', 1 });
    hnode[4].nodes.push_back({ 'C', 1 });
    hnode[4].nodes.push_back({ 'D', 1 });

}

void Graph::printAdjMatrix()
{
    cout << "The adjacency list that represents the graph is :";
    for (int i = 0; i < hnode.size(); i++)
    {
        cout << endl;
        cout << hnode[i].Name << " -> ";

        for (int j = 0; j < hnode[i].nodes.size(); ++j)
        {
            cout << hnode[i].nodes[j].nodeLink << ", " << hnode[i].nodes[j].cost << ", ";
        }
    }

    cout << endl;
    cout << endl;
    cout << endl;

    for (int i = 0; i < hnode.size(); i++)
    {
        cout << "Shortest distance from node " << Start << " to node " << hnode[i].Name << " is:" << weight[i] << endl;
        cout << "Shortest path is : ";

        for (int j = 0; j < path.size(); j++)
        {
            cout << path[j] << endl;
        }
    }
}

char Graph::LeastDistance(char node)
{
    int smallest = 9999;
    char smallestNode = node;
    int idx = 0;
    int i = GetIndex(node);

    for (int j = 0; j < hnode[i].nodes.size(); j++)
    {
        if ((node == hnode[i].Name) && (hnode[i].nodes[j].cost <= smallest) && (hnode[i].Visited == false))
        {
            smallest = hnode[i].nodes[j].cost;
            smallestNode = hnode[i].nodes[j].nodeLink;
            idx = i;
        }

    }
    hnode[idx].Visited = true;
    TotalCost = TotalCost + smallest;
    return(smallestNode);
}

void Graph::Dijkstra(char StartNode, char Destination)
{
    CurrentNode = StartNode;
    if (CurrentNode == Destination)
    {
        cout << "the start is the destination, therefore the cost will be 0." << endl;
    }
    else
    {
        cout << StartNode << "->";
        while (true)
        {
            if (CurrentNode != Destination)
            {
                CurrentNode = LeastDistance(CurrentNode);
                cout << CurrentNode << "->";
            }
            else if (CurrentNode == Destination)
            {
                cout << endl;
                cout << "The total cost of this path is:" << TotalCost;
                cout << endl;
                TotalCost = 0;//reset cost
                break;
            }
        }
    }
}

edit: I have changed the following lines from the top, the error is fixed but the output is still not as expected.

class Graph
{
    char Start;
    char StartNode;
    char CurrentNode;
    char Destination;
    int TotalCost = 0;
    vector<HeadNode> hnode;
    vector<char> path;
    vector<int> weight;

public:
    Graph();
    void createHeadNode(char X);
    void createAdjMatrix();
    char LeastDistance(char node);
    void printAdjMatrix();
    void Dijkstra(char StartNode, char Destination);
    void DestinationChangeCaller(char Start);
    char GetStartNode();
    int GetIndex(char CurrentNode);
};



int main()
{
    Graph graph;
    graph.createHeadNode('A');
    graph.createHeadNode('B');
    graph.createHeadNode('C');
    graph.createHeadNode('D');
    graph.createHeadNode('E');
    graph.createAdjMatrix();
    graph.GetStartNode();
    graph.DestinationChangeCaller(graph.GetStartNode());

    system("pause");
    return 0;
}

void Graph::DestinationChangeCaller(char Start)
{
    for (Destination = 'A'; Destination <= 'E'; Destination++)
    {
        Dijkstra(Start, Destination);
    }
}

There may be other issues but here is one:

char Graph::GetStartNode() // elementary get function with no error correction.
{
    char got;
    cout << "Please enter a node from A-E to start from:  ";
    cin >> got;
    cout << endl;
    return got;
}

So GetStartNode returns the user input. It doesn't update the member variable StartNode

And you don't use the return value when you call from main :

graph.createAdjMatrix();
graph.GetStartNode();    // <----- The return value isn't used
graph.DestinationChangeCaller();

So here:

void Graph::DestinationChangeCaller()
{
    for (Destination = 'A'; Destination <= 'E'; Destination++)
    {
        Dijkstra(StartNode, Destination);
                 ^^^^^^^^^
    }
}

StartNode is uninitialized.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM