邻接表无向图求最所有路径
思路:回溯法,递归思想,利用三个栈对需要的数据操作,一个是访问栈去存储访问过的邻点序号,一个是权值栈存储访问过的边权值,一个是打印栈方便我们将需要的内容打印出来。具体操作如下:先传进一个起点,如果该邻点未被访问,则访问该邻点并把访问位置1(1表示已访问,0表示未访问),同时将该邻点序号入访问栈并用权值栈去记录该点和邻点间的权值大小,接着判断该邻点是否是终点,如果是,就利用将访问栈和权值栈依次出栈到打印栈进行输出,输出完毕后再入访问栈和权值栈,再将该邻点(即终点)的访问位置0,出访问栈和权值栈,回溯判断如果起点还有其他邻点,则用next指针访问其他邻点。接上,如果该点已经访问(即访问位为1),则回溯访问该点其他邻点。利用上述步骤,递归找到所有路径打印出来。(结合回溯法,递归算法,深度优先遍历能更好的理解。)
graphlib.h
#include "graph.h"
#include <iostream>
#include <string>
#include "stacklib.h"//需要导入栈(这里不做导入)
using namespace std;
//查找两景点间所有路径
template <class DataType>
void ALGraph<DataType> :: display_allpath() {
int start,end, a;
cout << "请输入两个景点的序号:";
cin >> start>>end;
a = start;//记录起点序号;
for(int i=0; i<vertexNum; i++) {
adjlist[i].visit = 0;
}
adjlist[start].visit = 1;
stack_vertex(start,a , end);
}
LinkStack<int> L;//初始化访问栈
LinkStack<int> S;//初始化打印栈
LinkStack<int> W;//初始化权值栈
template <class DataType>
void ALGraph<DataType> :: stack_vertex(int start,int a, int end) {//第一个参数是递归的起始位置,第二第三个是起点和终点的位置
EdgeNode *p;
p = adjlist[start].firstEdge;
if (start == a) {
L.Push(start);//起点入栈
}
while(p != NULL) {
int pos;//表示邻点序号
int path;//表示边权值
pos = p->adjvex;
path = p->weight;
//0表示未访问
if(adjlist[pos].visit == 0) {
L.Push(pos);//未访问邻点入栈
W.Push(path);//未访问边权入栈
adjlist[pos].visit = 1;//该节点访问位置1
if (pos == end) {//判断邻点是否是终点
int c = -1;//记录访问位点序号
int n = 0;//记录出入栈次数
//将访问栈出栈到打印栈里面
for (int i=0; c!=a; i++) {
c = L.Pop();
S.Push(c);
n ++;
}
//将打印栈出栈打印信息,并重新入访问栈
for (int i=n; i>1; i--) {
c = S.Pop();
L.Push(c);
cout<< adjlist[c].vertex << "->";
}
S.Pop();
L.Push(end);
cout<<adjlist[end].vertex<<'\t';
int paths=0;//记录总长度;
//将权值栈出栈到打印栈里面
for (int i=n-1; i>0; i--) {
c = W.Pop();
cout<<c<<'\t';
S.Push(c);
paths += c;
}
cout<<"总长度:"<<paths<<endl;
//将打印栈出栈打印信息,并重新入权值栈
for (int i=n-1; i>0; i--) {
c = S.Pop();
W.Push(c);
}
adjlist[pos].visit = 0;//将终点访问位置0
L.Pop();//邻点出栈
W.Pop();//边权出栈
int b ;
b= L.GetTop();
if (start == b) {//判断起点下一个是否满足终点这种情况
p = p->next;//如果满足,终点出栈后重新访问起点下一个邻点,防止递归终止
continue;
}
return;//返回上一节点,退出递归
}
} else {//"如果1已经访问"
p = p->next;//访问下一个邻点
continue;
return;
}
stack_vertex(pos, a, end);//进入邻点递归
p = p->next;//该点访问下一邻点
}
adjlist[start].visit = 0;//当该点下一节点为空,证明该点邻点都访问完毕,将该点访问位置0
L.Pop();//将该点出栈
W.Pop();//将边权出栈
return;//退出递归
}
graph.h
#include <iostream>
#include <string>
using namespace std;
const int MaxSize = 10; //图的最多顶点数
int visited[MaxSize] = {0};
struct EdgeNode { //定义边表结点
int adjvex; //邻接点域
int weight; //边表权值
EdgeNode *next;
};
template <class DataType>
struct VertexNode { //定义顶点表结点
DataType vertex;
int visit;
EdgeNode *firstEdge;
};
template <class DataType>
class ALGraph {
public:
ALGraph(); //构造函数,建立n个顶点e条边的图
~ALGraph( ); //析构函数,释放邻接表各
void display_allpath();
void stack_vertex(int starts, int a, int end);
// private:
VertexNode<DataType> adjlist[MaxSize]; //存放顶点表的数组
int vertexNum, edgeNum; //图的顶点数和边数
};
main.cpp
#include <iostream> //引入输入输出流
#include "graphlib.h"
using namespace std;
int main() {
ALGraph<string> ALG; //建立具有5个顶点6条边的有向图
ALG.DispGraph();
ALG.display_allpath();
return 0;
}
创作不易~,记得点点关注点点赞哦!