所以我一直在研究这个程序,它的目标是使用递归和邻接矩阵来找出一个人可以通过地铁系统可以采取多少可能的路线,而不必多次通过轨道。这对我来说是不言自明的,但现在我迷失在程序2上,这是从C ++中的程序1和使用三个类和递归来做同样的问题。这些课程被认为是SubwaySystem,Station和Track。我真的不知道如何从简单的邻接矩阵过渡到三个类?这似乎适得其反,因为它似乎更复杂。我已经研究了一段时间了,我似乎无法利用所有三个班级。
我尝试过:我的方法是创建1个地铁系统,有12个站点,每个站点都有一个轨道阵列。例如,站A有一个可以到达的站B.在站A中有一个由12个轨道组成的阵列,但只有1个轨道被激活。但是我继续运行错误,因为我尝试初始化Track类中的数组,然后在SubwaySystem类中使用它们。然后尝试使用递归来获取所有可能的路由使得它变得更加困难。我真的不知道如何解决这个问题。
我的代码中的邻接矩阵几乎映射了从一个站到另一个站的整个连接。该站是对应于每行/列的A-L。我不知道如何使用邻接矩阵在没有的c ++ 中表示这一点。
我的C代码(程序1):
#include <stdio.h>
void routesFinder(int row, int col);
char station[13] = "ABCDEFGHIJKL";
char order[25] = "A";
int subway[12][12] = {{0,1,0,0,0,0,0,0,0,0,0,0},
{1,0,1,1,1,1,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,0},
{0,1,1,1,0,0,1,1,0,0,0,0},
{0,1,0,0,0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0,0,0,1,0},
{0,0,0,0,1,1,0,0,1,1,1,0},
{0,0,0,0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,1,1,1,1,0,1},
{0,0,0,0,0,0,0,0,0,0,1,0}};
int paths = 0, i = 1;
int main(){
routesFinder(0, 0); //start with first station row, first column
printf("\n%d days before repeating a route.\n", paths);
return 0;
}
void routesFinder(int row, int col) {
while (col < 12) { //go through columns of a row
if (subway[row][col] == 0) { // if no station is found in row
if (row == 11) { // station found
paths++;
printf("Route %d: %s.\n", paths, order);
return;
}
col++;
if (row != 11 && col == 12) { //backtracking from deadend
return;
}
}
if (subway[row][col] == 1) {
order[i] = station[col]; //add station to route
i++; //increment, prepare for next route
subway[row][col] = 0; //no track forward
subway[col][row] = 0; // or backward
routesFinder(col, 0); //recursion, look for path in new row
order[i] = '\0'; //remove route
i--; //decrement, prepare for next route
subway[row][col] = 1; //restore path
subway[col][row] = 1; // restore path
col++; //returning from deadend, check for next open path
if (row != 11 && col == 12) { //return from deadend
return;
}
}
}
}
答案 0 :(得分:2)
总的来说,我可以告诉你,特别是在c ++和面向对象中, 每个对象应该在系统中具有独特的作用。每一个都包含了一个自己负责的行为和知识。 至于你的具体问题 - 我没有深入研究这个问题,我认为这个想法是:
#include <iostream>
#include <string>
#include <vector>
class Track;
typedef std::vector<Track*> TrackList;
class Station
{
public:
Station( std::string name ) : _name( name ){};
~Station(){}
public:
const std::string& GetName() const
{ return _name; }
TrackList& GetTrackList()
{ return _trackList; }
void AddTrack( Track& track )
{ _trackList.push_back( &track ); }
private:
std::string _name;
TrackList _trackList;
};
class Track
{
public:
Track( Station& edgeA, Station& edgeB )
:
_edgeA( edgeA ),
_edgeB( edgeB ),
_wasVisited( false )
{
edgeA.AddTrack( *this );
edgeB.AddTrack( *this );
}
~Track(){}
public:
bool WasVisited() const
{ return _wasVisited; }
void SetVisited()
{ _wasVisited = true; }
public:
Station& GetEdgeA()
{ return _edgeA; }
Station& GetEdgeB()
{ return _edgeB; }
private:
Station& _edgeA;
Station& _edgeB;
bool _wasVisited;
};
class SubwaySystem
{
public:
SubwaySystem() {}
~SubwaySystem() {}
public:
void Traverse( Station& start )
{
TrackList& tracks = start.GetTrackList();
TrackList::iterator it = tracks.begin();
while ( it != tracks.end() )
{
if ( ! (*it)->WasVisited() )
{
std::cout << (*it)->GetEdgeA().GetName() << "-->" << (*it)->GetEdgeB().GetName() << ",";
(*it)->SetVisited();
Traverse( (*it)->GetEdgeB() );
}
++ it;
}
std::cout << std::endl;
}
};
int main()
{
Station A( "A" );
Station B( "B" );
Station C( "C" );
Station D( "D" );
Station E( "E" );
Track AB( A, B );
Track BC( B, C );
Track CA( C, A );
Track CD( C, D );
Track CE( C, E );
Track AE( A, E );
SubwaySystem subway;
subway.Traverse( A );
}
输出到
A-->B,B-->C,C-->A,A-->E,C-->E,
C-->D,
你可以使用Traverse功能“玩”并将打印件放在其他地方, 选择另一个结束递归条件等。
注意main()是多么干净。 你只需要声明电台和轨道,就会发生伏都教。 添加更多轨道很简单,只需描述链接即可,轨道已经“添加”到地铁中。
应用程序的其他部分也非常干净,因为每个类都知道它应该是什么,仅此而已。
答案 1 :(得分:0)
一种可能的方法是让地铁系统控制所有车站。然后,这些电台将拥有知道原点(它们来自哪个电台)和目的地(它们可以到达哪个电台)的轨道。
邻接矩阵将被分解,整个事物在地铁系统内表示,每个行/列在站中表示,并且每个1/0由轨道表示。没有跟踪零。
将在站级确定要采用的路径,使用的轨道/目的地已经到达。轨道可以有一个属性,如果它们被骑在那里就可以跟踪。
答案 2 :(得分:0)
如果你在C中这样做,你可能会有这样的结构
typedef struct node node;
typedef struct edge edge;
typedef struct graph graph;
struct graph { // subway system
node *nodes; // stations
};
struct node { // station
char *name;
edge *edges; // tracks connected to this station
node *next; // next node in graph
bool visited;
}
struct edge { // track
node *src; // from station
node *dst; // to station
edge *next; // next track, this station
bool visited;
}
将其转换为类应该很容易。除了他们可能希望你使用stl数据结构而不是简单地像我一样内联列表。
简单的递归图算法很好地映射到这些数据结构。
答案 3 :(得分:0)
计算递归的想法有点难以获得,但让我尝试解释至少那部分。
所以你知道strlen是如何工作的,对吗?你走数组并保持计数。但这是一个递归版本
unsigned int strlen(const char * string) {
if (*string == '\0') { return 0; }
else return 1 + strlen(string + 1);
}
你看到它是如何工作的吗?在走一个可以使用简单计数器的数组时没有那么有用,但是当你处理有多种可能的服务组合或多种方式的问题时,它可以很好地工作。例如,如果要计算二叉树中的节点数,可以执行类似的操作。
unsigned int treecount(NODE * node) {
if (node == NULL) { return 0;}
else return 1 + treecount(node->left) + treecount(node->right);
}
希望这会有所帮助。查理伯恩斯可能是正确的,用图表做这个是个好主意。