以编写导航系统为背景,如果我们把每个地点设置从0开始设置一个唯一编号,把地点之间的距离记为无向带权图中的权值,再用邻接矩阵存储这张图的话。
使用下面原创算法可以实现输出指定两点间的所有路径(这里的所有路径指不论距离远近只要是一个与之前不同的路径都算在内)
核心思路就是:首先从begin出发,检测矩阵中所在行是否有目标点,若有,则输出之前存储的路径(一般是通过path数组输出路径,distance输出路程),进入下一轮循环,若无,则从不是MAX的地方递归进去下一个函数,重复上述步骤。
#define MAX 9999 //MAX代表邻接矩阵中一个不可能到达的数值,可以自定义
class Map
{
private:
int **_Linjie; //邻接矩阵二维数组的指针
int _dots; //点数
void Show_path(vector<int> path , vector<int> distance , Location &L); //按照路径数组从头到位输出路径以及路程
int Is_repeat(int i , vector<int> path); //判断path中是否有i,有返回1,没有返回0
public:
Map();
void Find_all_path(int begin , int end , vector<int> path , vector<int> distance); //寻找并输出两点间所有路径
};
vector<int> path;
vector<int> distance;
path.push_back(begin); //注意使用下面函数之前先在path中插入begin
void Map::Find_all_path(int begin , int end , vector<int> path , vector<int> distance) //这是一个递归函数,它写在了Map类里面,begin是起点,end是终点,但对于本算法没有任何区别可以随意互换,path存放路径点,distance存放每次记录的权值,当我们初次使用此函数时path中应该是存有一个begin的
{
//记录前面递归下来的path和distance,后面有用
vector<int> p = path;
vector<int> d = distance;
for(int i = 0 ; i < this->_dots ; ++i) //遍历一行中的值
{
if(this->Is_repeat(i , path)) //这里的函数用来判断i是否在path中出现过,如果是返回1,否则返回0
{
continue;
}
if(_Linjie[path[path.size()-1]][i] != MAX)
{
if(i == end) //表示找到了end,下面是输出路径前的准备工作
{
distance.push_back(this->_Linjie[path[path.size()-1]][end]);
path.push_back(end);
this->Show_path(path , distance); //输出路径的函数,可以自己写
path = p;
distance = d;
continue;
}
else //这里是没找到end
{
distance.push_back(_Linjie[path[path.size()-1]][i]);
path.push_back(i);
this->Find_all_path(begin , end , path , distance);
path = p;
distance = d;
}
}
}
}
比如,我使用下面这个图
把图中点与点之间的路径等信息提前输入程序或者在文本文件中保存从0-8依次对应a-k,显示在程序中
比如我们查询0到4的全部路径:
上图输出的路径信息的样子取决于代码中Show_path()函数的函数体,所以你想怎样输出都可以自己定义。
换两个点也是可以的,比如:
最后,感谢阅读我的文章,如果觉得它有那么一丢丢自己的理解的话,请点赞鼓励一下作者,再次感谢。