最短路径算法目录
- 一.什么是最短路径
- 二.最短路径算法的实现
- 1.准备工作
- 2.拆解为子问题——递归
- 三.完整代码
一.什么是最短路径
顾名思义根据需求,可以获取的最优的路径.
比如说:
我标的数值,就是时间,那么假如我们是A点到D点.
那么我们可以看到有三条路径:
A->E->D所花时间:36分钟
A->C->D所花时间:25分钟
A->B->D所花时间:26分钟
那么如果我们根据时间来看待问题的话,那么A->C->D就是我们的最短路径.
当然也可以其他的信息作为我们的判断,我们称之为权重.
下面我们将用深度优先的方式来实现最短路径算法.
二.最短路径算法的实现
1.准备工作
我们既然要找出最短路径,那么我们需要记录路径.
我们需要一个保存路径的数组,和一个保存最短路径的数组.
同时我们还需要一个权值用于来比较.
走过的步数我们可以当做路径数组的下标.
这里的位置我们设置为整数的最大值,方便我们将第一个权重设置.
记得要设置权重哦在创建图的时候.
2.拆解为子问题——递归
如果我们的路径是A->D,那么我们可以分为A->E,E->D.
用递归的实现来进行访问.
那么当我们输入的终点等于起点,那么就说明走到了目的地.
当达到目的地的时候,我们就将这条路径打印出来,并将此时的权重与最小权重进行相比,如果更小,那么我们就将这条路径复制到最短路径.
已经访问到了节点,我们还是设置为true.
现在我们开始拿起点的邻接点,然后作为新的起点来递归,直到起点等于终点打印完路径设置好最低路径,然后就回退.
当我们回退的时候,姚将走过的路径又设置为空,并且设置为未访问,因为我们的其他路径也要访问目的地的节点.
路径数组的图解过程:
三.完整代码
#include <iostream>
#include <queue>
using namespace std;
#define MaxSize 1024
typedef struct _EdgeNode//与节点连接边的定义
{
int adjvex;//邻接的顶点
int weight;//权重
struct _EdgeNode* next;//下一条边
}EdgeNode;
typedef struct _VertexNode//顶点节点
{
char data;//节点数据
EdgeNode* first;//指向邻接第一条边,头节点
}VertexNode,AdjList;
typedef struct _AdjListGraph
{
AdjList* adjlist;
int vex;//顶点数
int edge;//边数
}AdjListGraph;
bool visited[MaxSize];//全局数组,用来记录节点是否已被访问
int Location(AdjListGraph& G, char c);
//图的初始化
void init(AdjListGraph& G)
{
G.adjlist = new AdjList[MaxSize];
G.edge = 0;
G.vex = 0;
for (int i = 0; i < MaxSize; i++)
{
visited[i] = false;
}
}
//图的创建
void Create(AdjListGraph& G)
{
cout << "请输入图的顶点数以及边数:" << endl;
cin >> G.vex >> G.edge;
cout << "请输入相关的顶点:" << endl;
for (int i = 0; i < G.vex; i++)
{
cin >> G.adjlist[i].data;
G.adjlist[i].first = NULL;
}
char v1=0, v2=0;//保存输入顶点的字符
int i1, i2;//保存顶点在数组中的下标
int weight = 0;//保存边的权重
cout << "请输入相关联边的两个顶点和权重:" << endl;
for (int i = 0; i < G.edge; i++)
{
cin >> v1 >> v2>>weight;
i1 = Location(G, v1);
i2= Location(G, v2);
if (i1!=-1 && i2!=-1)//寻找到位置
{
EdgeNode* temp = new EdgeNode;
temp->adjvex = i2;
temp->next = G.adjlist[i1].first;
temp->weight = weight;
G.adjlist[i1].first = temp;
}
}
}
//通过顶点对应的字符寻找顶点在图中的邻接点
int Location(AdjListGraph& G, char c)
{
for (int i = 0; i < G.vex; i++)
{
if (G.adjlist[i].data == c)
{
return i;
}
}
return -1;
}
//对图上的顶点进行深度遍历
void DFS(AdjListGraph& G, int v)
{
int next = -1;
if (visited[v])return;//如果已经访问
cout << G.adjlist[v].data << " ";
visited[v] = true;//设置为已经访问
EdgeNode* temp = G.adjlist[v].first;
while (temp)
{
next = temp->adjvex;
temp = temp->next;
if (visited[next] == false)
{
DFS(G, next);
}
}
}
int min_weights = 0x7FFFFFFF;//int类型整数最大值,32位
int steps = 0;//已经走过的步数
int path[MaxSize] = { 0 };//保存走过的路径
int shortest_path[MaxSize] = { 0 };//保存最短的路径
//深度遍历求解起点到终点的最短路径
void DFS(AdjListGraph& G,int start,int end, int weights)
{
int cur = -1;
if (start == end)//已经找到终点,不用继续遍历
{
for (int i = 0; i < steps; i++)
{
cout << G.adjlist[path[i]].data << " ";//输出可能的路径
}
printf("\t\t该路径长度是:%d\n", weights);//输出对应路径长度
if (min_weights > weights)
{
min_weights = weights;
memcpy(shortest_path, path, steps * sizeof(int));
}
return;
}
visited[start] = true;//设置为已经访问
EdgeNode* temp = G.adjlist[start].first;
while (temp)
{
int weight = temp->weight;
cur = temp->adjvex;
if (visited[cur] == false)
{
visited[cur] = true;//标记cur 已访问
path[steps++] = cur;//保存路径到path 数组中
DFS(G, cur, end, weights + weight);
visited[cur] = false;//前一步探索完成后,置cur顶点为未选择状态
path[--steps] = 0;
}
temp = temp->next;
}
}
//对使用顶点进行深度遍历
void DFS_Main(AdjListGraph& G)
{
for (int i = 0; i < G.vex; i++)
{
if (visited[i] == false)
{
DFS(G, i);
}
}
}
void BFS(AdjListGraph& G, int v)
{
queue<int> q;
int cur = -1;
int index = -1;
q.push(v);
while (!q.empty())//队列不为空
{
cur = q.front();
if (visited[cur] == false)//当前的顶点还没有被访问
{
cout << G.adjlist[cur].data << " ";
visited[cur] = true;
}
q.pop();//出队列
EdgeNode* temp = G.adjlist[cur].first;
while (temp!=NULL)
{
index = temp->adjvex;
temp = temp->next;
if (visited[index] == false)
{
q.push(index);
}
}
}
}
void BFS_Main(AdjListGraph& G)
{
for (int i = 0; i < G.vex; i++)
{
if (visited[i] == false)
{
BFS(G, i);
}
}
}
/*
6 7
A B C D E F
A B
B D
A C
C D
A E
E D
F A
5 6
A B C D E
A B 10
B D 16
A C 15
C D 10
A E 19
E D 17
A D
*/
int main()
{
AdjListGraph G;
//初始化
init(G);
//创建图
Create(G);
//深度遍历
//DFS_Main(G);
//广度遍历
//BFS_Main(G);
char start, end;
cout << "请输入要查询的最短路径的起点和终点:" << endl;
cin >> start >> end;
//求两点间的最短路径
DFS(G, Location(G, start), Location(G, end), 0);
cout << "最短路径: ";
int i = 0;
while (i < MaxSize && shortest_path[i]>0)
{
cout << G.adjlist[shortest_path[i]].data << " ";
i++;
}
cout << endl;
system("pause");
}
运行结果: