简体   繁体   中英

Pathfinding in C++ using recursion

I'm attempting to print out the 640 paths in this subway system. I know there are 640 paths, as I already did this program with an adjacency matrix. Now I need to do it with classes. The first station begins at 'a', and the path ends at station 'l'. I am having trouble implementing the recursive function, SearchRoute, as I need to print the path, flag the path, and then unflag the path again to allow for backtracking. Currently I can only print the track that is 'a' to 'b', so something is severely wrong with my recursive function. Any advice would be appreciated

header

//Function Declarations 

#include <iostream>
#include <string>


using namespace std; 

#ifndef SUBWAY_H
#define SUBWAY_H


class Track
{
    public:
    //Default Constructor 
    Track();

    //Overload Constructor
    Track(char, char);

    //Destructor 
    ~Track();

    //Member variables 
    char node_1;
    char node_2;
    bool visited; 
};


class Station
{
    public:
    //Default Constructor 
    Station();

    //Destructor 
    ~Station();

    //Overload Constructor
    Station(char, int, int);

    //Member variables 
    char station_name; 
    int track_starting_ID;
    int track_size; 
};


class SubwaySystem
{
    public:
    //Default Constructor
    SubwaySystem();

    //Destructor 
    ~SubwaySystem();

    //Recursive function
    void SearchRoute(int);

    //Other member functions 
    friend ostream& operator<<(ostream& os, const Track& my_track);
    friend ostream& operator<<(ostream& os, const Station& my_station);


    //Member variables 
    Track my_track[34];
    Station my_station[12];

    int count_routes; 
    int Current_Station_ID;

    //String to save found route 
};



#endif

cpp

//Function Definitions
#include <iostream>
#include <string>

#include "subway.h"

using namespace std; 


Track::Track()
{
    visited = 0; 
}


Track::~Track(){

}


Track::Track(char pass_track1, char pass_track2)
{
    node_1 = pass_track1;
    node_2 = pass_track2;
}


Station::Station(){

}


Station::~Station(){

}


Station::Station(char pass_station_name, int pass_start, int pass_size){
    station_name = pass_station_name;
    track_starting_ID = pass_start;
    track_size = pass_size; 
}


SubwaySystem::SubwaySystem()
{
    //Initialize tracks 
    //node_1, node_2
    my_track[0] = Track('a', 'b');
    my_track[1] = Track('b', 'a');
    my_track[2] = Track('b', 'c');
    my_track[3] = Track('b', 'd');
    my_track[4] = Track('b', 'e');
    my_track[5] = Track('b', 'f');
    my_track[6] = Track('c', 'b');
    my_track[7] = Track('c', 'e');
    my_track[8] = Track('d', 'b');
    my_track[9] = Track('d', 'e');
    my_track[10] = Track('e', 'b');
    my_track[11] = Track('e', 'c');
    my_track[12] = Track('e', 'd');
    my_track[13] = Track('e', 'g');
    my_track[14] = Track('e', 'h');
    my_track[15] = Track('f', 'b');
    my_track[16] = Track('f', 'h');
    my_track[17] = Track('g', 'e');
    my_track[18] = Track('g', 'k');
    my_track[19] = Track('h', 'e');
    my_track[20] = Track('h', 'f');
    my_track[21] = Track('h', 'i');
    my_track[22] = Track('h', 'j');
    my_track[23] = Track('h', 'k');
    my_track[24] = Track('i', 'h');
    my_track[25] = Track('i', 'k');
    my_track[26] = Track('j', 'h');
    my_track[27] = Track('j', 'k');
    my_track[28] = Track('k', 'g');
    my_track[29] = Track('k', 'h');
    my_track[30] = Track('k', 'i');
    my_track[31] = Track('k', 'j');
    my_track[32] = Track('k', 'l');
    my_track[33] = Track('l', 'k');

    //Initialize stations 
    //station_name, track_starting_ID, track_size 
    my_station[0] = Station ('a', 0, 1);
    my_station[1] = Station ('b', 1, 5);
    my_station[2] = Station ('c', 6, 2);
    my_station[3] = Station ('d', 8, 2);
    my_station[4] = Station ('e', 10, 5);
    my_station[5] = Station ('f', 15, 2);
    my_station[6] = Station ('g', 17, 2);
    my_station[7] = Station ('h', 19, 5);
    my_station[8] = Station ('i', 24, 2);
    my_station[9] = Station ('j', 26, 2);
    my_station[10] = Station ('k', 28, 5);
    my_station[11] = Station ('l', 33, 1); 

    //Initiaize other members 
    count_routes = 0; 
    Current_Station_ID = 0;
}


SubwaySystem::~SubwaySystem()
{
}


ostream& operator<<(ostream& os, const Track& my_track)
{
    os << my_track.node_1 << '.' << my_track.node_2;
    return os;
}


ostream& operator<<(ostream& os, const Station& my_station)
{
    os << my_station.station_name << '.' << my_station.track_starting_ID << '.' << my_station.track_size;
    return os;
}


void SubwaySystem::SearchRoute(int Current_Station_ID)
{
    while (Current_Station_ID < 33)
    {
        if (Current_Station_ID == 0) //Find a successful route to Station L
        {
            count_routes++; //Add 1 into the variable “count_routes”
            cout << count_routes << " " << my_track[Current_Station_ID] << endl; //Print out this route 
            return; 
        }

        else //Get into recursive Function Body
        {
            for (int i = my_station[Current_Station_ID].track_starting_ID; i < my_station[Current_Station_ID].track_starting_ID + my_station[Current_Station_ID].track_size; i++)
            {
                if (my_track[Current_Station_ID].visited == 0) //if this track is not visited before
                {
                    my_track[Current_Station_ID].visited = 1; //mark this track as visited
                    my_track[Current_Station_ID].node_2 = 1; //mark its corresponding track as visited
                    cout << my_track[Current_Station_ID] << endl; //save this track
                    SearchRoute(Current_Station_ID + 1); //Recursive
                    i--; //Backtrack this track
                    my_track[Current_Station_ID].visited = 0;//mark this track as unvisited
                    my_track[Current_Station_ID].node_2 = 0;//mark its corresponding track as unvisited
                }
            }
        }
    }
}

main

#include <iostream>
#include <string>

#include "subway.h"

using namespace std; 

int main(int argc, char **argv)
{
    SubwaySystem Test; 
    Test.SearchRoute(0);
}

Why is there a return statement in

     if (Current_Station_ID == 0) //Find a successful route to Station L
    {
        count_routes++; //Add 1 into the variable “count_routes”
        cout << count_routes << " " << my_track[Current_Station_ID] << endl; //Print out this route 
        return; 
    }

(Probably worthy of only a comment, but I hate pasting code in comments)

As far I can see you have not initialized all members in the constructor. At least in the Track. The right ctor looks like:

Track::Track(char pass_track1, char pass_track2)
{
    node_1 = pass_track1;
    node_2 = pass_track2;
    visited = false;              // this was missing
}

In C++ you have to initialize all members in all constructors. Otherwise the values has the values which was before in the memory. The chance that there is a 0 in the visited member is 1:2^32 => near to zero.

Hi @ace : much as Frank suggested you need to initialise all variables. However I would also include a default constructor which makes single piece tracks and utilises the overloaded constructor:

Track::Track()    {        Track("~","~");    }
Track::Track(char pass_track1, char pass_track2)
{
    node_1 = pass_track1;
    node_2 = pass_track2;
    visited = false;
}

This means the base constructor will always make a single piece track from "~" to "~" (can be any character) I would also use a character for the base constructor which you will not use in real use, that way you can track and trace problems in the future and it becomes evident when the default constructor is being utilised at a glance, simply because it contains said character of your choice.

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