表达式:向量下标超出范围(Visual C ++)

时间:2015-11-07 20:41:47

标签: c++ graph adjacency-list

我的代码有问题。建设时我没有收到任何错误。但是在调试时会有一个信息:"表达式:向量下标超出范围"。

我将在这里放置整个代码(使用Adjacency List表示图形)。 我对每个答案都表示感谢。 感谢。

Graph.h

#include <stdio.h>
#include <iostream>
#include <list>
#include <exception>

using namespace std;

class Graph
{
public:
    /*
    Adds an edge between given vertices. Third argument is a weight of an edge (1 by default).
    If the edge already exists or we try to add a loop, no edge is added.

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - we try to create a loop
    - there are no such vertices
    - if the edge already exists
    */
     virtual void addEdge(int u,int v,int weight=1) =0;

     /* 
     Removes an edge between given vertices. 
     If the edge does not exist, nothing is changed.

     Error handling:
     throw std::invalid_argument with appropriate message if:
     - an edge does not exist
     - vertices do not exist
     */
     virtual void removeEdge(int, int) =0;

    /*
    Returns:
    1 if given vertices are connected by an egde
    0 if the vertices are not connected

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - vertices do not exist
    */
     virtual int areConnected(int,int) =0;

     /*
    Returns:
    the weight of an edge between given vertices.

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - an edge does not exist
    - vertices do not exist
    */
     virtual int getWeight(int,int) =0;

     /*
     Prints the representation of a graph.
     */
    virtual void show() =0;   


    /*
    Returns the number of vertices in a graph.
    */
     virtual int getVerticesCount() =0;

     /*
    Returns the number of edges in a graph.
    */
     virtual int getEdgesCount() =0;    

     /*
     Returns:
     degree of the given vertex

     Error handling:
     throw std::invalid_argument with appropriate message if:
    - vertex does not exist
     */
    virtual int getDegree(int) =0;  

    /* Return a pointer to the clone of the graph (with the same representation) */
    virtual Graph* clone() =0;

    /* Return a pointer to the empty graph with n vertices and the same representation */
    virtual Graph* empty(int) =0;

};

AdjacencyListGraph.h

#include "Graph.h"
#include <vector>

using namespace std;

class AdjacencyListGraph: 
    public Graph
{
public:
     /*
     creates a graph with given number of vertices and no edges
     */
     AdjacencyListGraph(int n=0);
     /*
     creates a copy of a given graph
     */
     AdjacencyListGraph(const AdjacencyListGraph&); 
     ~AdjacencyListGraph();                 

     void show() override;   
     int getVerticesCount() override;           

     void addEdge(int,int,int) override;
     void removeEdge(int, int) override;
     int getEdgesCount() override;  
     int getDegree(int) override;
     int areConnected(int,int) override;        
     int getWeight(int,int) override; 

     Graph* clone() override;
     Graph* empty(int) override;

private:
    /*
        adjacency list
        add whatever is necessary here
    */
    int n;  
    vector<vector<int>> neighbors;
    vector<vector<int>> weights;

};

AdjacencyListGraph.cpp

#include "AdjacencyListGraph.h"

/*
 creates a graph with given number of vertices and no edges
*/
AdjacencyListGraph::AdjacencyListGraph(int n) : neighbors(0), weights(0), n(n){}

/*
 creates a copy of a given graph
*/
AdjacencyListGraph::AdjacencyListGraph(const AdjacencyListGraph& other)
{
    this->n = other.n;
    this->neighbors = other.neighbors;
    this->weights = other.weights;
}

/* destructor */
AdjacencyListGraph::~AdjacencyListGraph()
{
    neighbors.clear();
    weights.clear();
}

////////////////////////////////////////////////////////

/*
 Prints the representation of a graph. Make sure that weight are visible.
 Exemplary representation:

0: 1(2) 4(5)
1: 0(2)
2:
3:
4: 0(5)

 Complexity O(n^2)
*/
void AdjacencyListGraph::show()
{
    int i=0;
    while(i < this->n)
    {
        cout << i << ": ";
        size_t j=0;
        while(j < neighbors[i].size())
        {
            cout << neighbors[i][j] << "(" << weights[i][j] << ") ";
            j++;
        }
        cout << endl;
        i++;
    }
}

/*
Returns the number of vertices in a graph.

Complexity O(1)
*/
int AdjacencyListGraph::getVerticesCount()
{
    return n;
}

///////////////////////////////////////////////////////

    /*
    Adds an edge between given vertices. Third argument is a weight of an edge (1 by default).
    If the edge already exists or we try to add a loop, no edge is added.
    Assume that weights are positive integers.

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - we try to create a loop
    - there are no such vertices
    - if the edge already exists

    Complexity O(n)
    */
void AdjacencyListGraph::addEdge(int u,int v, int weight)
{
    //throw invalid_argument("this is the way you throw exception with a given message");   
    if(u==v)
        throw invalid_argument("creating a loop is not allowed");

    int a=1;
    for(int g=0; g<n; ++g)
    {
        if(g!=u)
            continue;
        else if(g==u)
        {
            a=2;
            break;
        }
    }
    if(a==1)
        throw invalid_argument("the vertex does not exist");

    int b=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=v)
            continue;
        else if(h==v)
        {
            b=2;
            break;
        }
    }
    if(b==1)
        throw invalid_argument("the vertex does not exist");

    if(weights[u][v]>0)
        throw invalid_argument("the edge already exists");
    else    
    {
        neighbors[u].push_back(v);
        weights[u][v]=weight;
    }   
}

     /* 
     Removes an edge between given vertices. 
     If the edge does not exist, nothing is changed.

     Error handling:
     throw std::invalid_argument with appropriate message if:
     - an edge does not exist
     - vertices do not exist

     Complexity O(n)
     */
void AdjacencyListGraph::removeEdge(int u, int v)
{
    if(weights[u][v]==0)
        throw invalid_argument("the edge does not exist");

    int a=1;
    for(int g=0; g<n; ++g)
    {
        if(g!=u)
            continue;
        else if(g==u)
        {
            a=2;
            break;
        }
    }
    if(a==1)
        throw invalid_argument("the vertex does not exist");

    int b=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=v)
            continue;
        else if(h==v)
        {
            b=2;
            break;
        }
    }
    if(b==1)
        throw invalid_argument("the vertex does not exist");

    for(int j=0; j<n; ++j)
    {
        if(j==u)
        {
            for(size_t i=0; i<neighbors[j].size(); ++i)
            {
                if(neighbors[j][i]==v)
                {
                    weights[u][v] = 0;
                    cout << "the edge is removed";
                    return;
                }
            }
        }
    }
}

/*
    Returns the number of edges in a graph.

    Complexity O(n^2)
*/
int AdjacencyListGraph::getEdgesCount()
{
    int count=0;
    for(int i=0; i<n; ++i)
        for(size_t j=0; j<neighbors[i].size(); ++j)
        {
            if(weights[i][j]>0)
                count++;
            else
                continue;
        }
    return count/2;
}

     /*
     Returns:
     degree of the given vertex

     Error handling:
     throw std::invalid_argument with appropriate message if:
    - vertex does not exist

    Complexity O(n)
     */
int AdjacencyListGraph::getDegree(int v)
{
    int b=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=v)
            continue;
        else if(h==v)
        {
            b=2;
            break;
        }
    }
    if(b==1)
        throw invalid_argument("the vertex does not exist");

    int degree=0;
    for(int i=0; i<n; ++i)
    {
        if(i==v)
        {
            for(size_t j=0; j<neighbors[i].size(); ++j)
            {
                    if(weights[i][j]>0)
                        degree++;
            }
            return degree;
        }
    }
}

    /*
    Returns:
    1 if given vertices are connected by an egde
    0 if the vertices are not connected

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - vertices do not exist

    Complexity O(n)
    */
int AdjacencyListGraph::areConnected(int v,int w)
{
    int a=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=v)
            continue;
        else if(h==v)
        {
            a=2;
            break;
        }
    }
    if(a==1)
        throw invalid_argument("the vertex does not exist");

    int b=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=w)
            continue;
        else if(h==w)
        {
            b=2;
            break;
        }
    }
    if(b==1)
        throw invalid_argument("the vertex does not exist");

    for(int j=0; j<n; ++j)
    {
        if(j==v)
        {
            for(size_t i=0; i<neighbors[j].size(); ++i)
            {
                if(neighbors[j][i]==w)
                    if(weights[v][w]>0)
                        return 1;
            }
            return 0;
        }
    }
}

     /*
    Returns:
    the weight of an edge between given vertices.

    Error handling:
    throw std::invalid_argument with appropriate message if:
    - an edge does not exist
    - vertices do not exist

    Complexity O(n)
    */
int AdjacencyListGraph::getWeight(int u, int v)
{
    int a=1;
    for(int g=0; g<n; ++g)
    {
        if(g!=u)
            continue;
        else if(g==u)
        {
            a=2;
            break;
        }
    }
    if(a==1)
        throw invalid_argument("the vertex does not exist");

    int b=1;
    for(int h=0; h<n; ++h)
    {
        if(h!=v)
            continue;
        else if(h==v)
        {
            b=2;
            break;
        }
    }
    if(b==1)
        throw invalid_argument("the vertex does not exist");

    if(weights[u][v]==0)
        throw invalid_argument("the edge does not exist");

    int weight=0;
    for(int i=0; i<n; ++i)
    {
        if(i==u)
        {
            for(size_t j=0; j<neighbors[i].size(); ++j)
            {
                    if(neighbors[i][j]==v)
                    {
                        weight=weights[i][j];
                        return weight;
                    }
            }
        }
    }
}

Graph* AdjacencyListGraph::clone()
{
    Graph *c = new AdjacencyListGraph(*this);
    return c;
}

Graph* AdjacencyListGraph::empty(int n=0)
{
    Graph *c = new AdjacencyListGraph(n);
    return c;
}

的main.cpp

#include "AdjacencyListGraph.h"

void main()
{
    Graph &g = AdjacencyListGraph(4);
    try
    {
        cout << "add loop (0,0): ";
        g.addEdge(0,0);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }


    try
    {
        cout << "add edge with non-existing end (0,7): ";
        g.addEdge(0,7);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }

    g.show();

    cout << "add edge (0,1,3)"<<endl;
    g.addEdge(0,1,3);

    cout << "add edge (0,2)"<<endl;;
    g.addEdge(0,2);

    cout << "get weight (0,1): " << g.getWeight(0,1) <<" should be 3"  << endl;
    cout << "get weight (0,2): " << g.getWeight(0,2) <<" should be 1"  << endl;

    Graph* g1 = g.clone();
    g1->show();
    try
    {
        cout << "add loop (1,1): ";
        g1->addEdge(1,1);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }
    cout<<endl;
    cout << "add edge (1,2)"<<endl;
    g.addEdge(1,2);
    cout << "add edge (2,3)"<<endl;
    g.addEdge(2,3);
    try
    {
        cout << "add duplicate edge (2,3,7): ";
        g.addEdge(2,3);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }
    cout << "get weight (2,3): " << g.getWeight(2,3) << " should be 1"  <<endl;
    g.show();
    cout<<endl;
    g1->show();

    cout << "remove edge (1,2)"<<endl;
    g.removeEdge(1,2);

    try
    {
        cout << "remove non-existing edge (1,2): ";
        g.removeEdge(1,2);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }
    try
    {
        cout << "remove edge with non-existing end (1,7): ";
        g.removeEdge(1,7);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }


    cout << "check edge (0,1): " << g.areConnected(0,1) <<" should be 1"     << endl;
    cout << "check edge (0,3): " << g.areConnected(0,3) <<" should be 0"     << endl;

    try
    {
        cout << "check edge with wrong end (0,7): "<< g.areConnected(0,7);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }
    try
    {
        cout << "check edge with wrong end (-1,7): "<< g.areConnected(0,7);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }


    cout << "vertices: " << g.getVerticesCount() <<" should be 4" << endl;
    cout << "edges: " << g.getEdgesCount() <<" should be 3" << endl;

    cout << "deg(0): " << g.getDegree(0) <<" should be 2" << endl;

    try
    {
        cout << "check degree of non-existing vertex deg(7): " << g.getDegree(7);
        cout<<" - should throw invalid_argument exception"<<endl;
    }
    catch (invalid_argument& e)
    {
        cout<<"Exception: "<<e.what()<<" - OK"<<endl;
    }   

    delete g1;
    system("pause");
}

0 个答案:

没有答案