我的代码有问题。建设时我没有收到任何错误。但是在调试时会有一个信息:"表达式:向量下标超出范围"。
我将在这里放置整个代码(使用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");
}