迪杰斯特拉(dijkstra)算法是单源最短路径问题的求解方法。参考链接:算法之迪杰斯特拉(dijkstra)非常详细介绍_PRML_MAN的博客-CSDN博客_迪杰斯特拉
使用上面的链接提供的图片进行测试
从v0(家)到v7(学校)的最短路径如下图所示
以上图片的邻接矩阵如下所示:
float G[][8] = {
0, 4, 3, 10, -1, -1, -1, -1,
4, 0,-1, 3, 8, -1, -1, -1,
3, -1, 0, 5, -1, -1, 12, -1,
10, 3, 5, 0, 3, 12, -1, -1,
-1, 8,-1, 3, 0, 3, -1, 5,
-1,-1,-1, 12, 3, 0, -1, 1,
-1,-1,12, -1, -1, -1, 0, 2,
-1,-1,-1, -1, 5, 2, 2, 0
};
可以追溯路径的代码
#include <iostream>
#include <string>
#include <vector>
void dij_learn();//函数声明
void main() {
dij_learn();
}
class node {//节点结构
public:
int index;
float way;
std::vector<node*> childs;
};
node diji(float G[][8], int start, float end);//函数声明
node iterate_tree(node tree, int end, std::vector<node>* result);//函数声明
void dij_learn() {
float G[][8] = {
0, 4, 3, 10, -1, -1, -1, -1,
4, 0,-1, 3, 8, -1, -1, -1,
3, -1, 0, 5, -1, -1, 12, -1,
10, 3, 5, 0, 3, 12, -1, -1,
-1, 8,-1, 3, 0, 3, -1, 5,
-1,-1,-1, 12, 3, 0, -1, 1,
-1,-1,12, -1, -1, -1, 0, 2,
-1,-1,-1, -1, 5, 2, 2, 0
};
diji(G, 0, 7);
}
node diji(float G[][8], int start, float end) {//迪杰斯特拉方法
//G表示一个图,start和end表示起点和重点(序号从0开始)
//G中-1代表不邻接
//初始化start节点
node start_n;
start_n.index = start;
start_n.way = 0;
std::vector<node*> N;//用于存放已经访问过的节点
N.push_back(&start_n);
node* min_node_father = new node();
std::vector<int> visit(sizeof(G), 0);
visit[start] = 1;
//vector<int> dis(sizeof(G), INT_MAX);//该变量用于存储最短路径值
while (1) {
int min_point_index = -1;
float min_dis = INT_MAX;
for (int i = 0; i < N.size(); i++) {//遍历当前队列所有点的邻接点
//查询G,即获得点的邻接点信息
float* L = G[N[i]->index];
for (int j = 0; j < sizeof(L); j++) {
if (L[j] == -1 || visit[j] == 1 || i == j) {//已访问或不邻接的点跳过
continue;
}
if (L[j] + N[i]->way < min_dis) {//记录最短路径
min_node_father = N[i];
min_point_index = j;
min_dis = L[j] + N[i]->way;
}
}
if (if_findend) {
break;
}
}
if (min_point_index == -1) {//当无法选出最短路径节点时,表面图已经结束,或者无法再继续搜寻
break;
}
node* min_n = new node;
min_n->index = min_point_index;
min_n->way = min_node_father->way + G[min_node_father->index][min_point_index];
min_node_father->childs.push_back(min_n);
visit[min_point_index] = 1;
N.push_back(min_n);
min_node_father = nullptr;
if (if_findend) {
break;
}
}
std::vector<node>* result = new std::vector<node>;//获取从tree到end的最短路径,结果存储在result里面
node ways = iterate_tree(*N[0], end,result);
result->push_back(ways);//最后将起点存入路径中
return ways;
}
node iterate_tree(node tree, int end, std::vector<node>* result) {//获取从tree到end的最短路径,结果存储在result里面
//遍历迪杰斯特拉生成树,tree就是开头,end就是目的地
node n;
node null_node; null_node.index = -1;
if (tree.index == end) {
return tree;
}
else if (tree.childs.size() == 0 || tree.index == -1) {
return null_node;
}
for (int i = 0; i < tree.childs.size(); i++) {
n = iterate_tree(*tree.childs[i], end, result);
if (n.index == end) {
result->push_back(n);
return tree;
}
else if (n.index != -1) {
result->push_back(n);
return tree;
}
}
return null_node;
}
运行结果:(从v0到v7)0-1-3-4-5-7,way存储的是从原点到各个节点的最短路径
该算法在点云中的应用(计算近似测地线距离)