这里不说废话,直接看代码,实现Dijsk最短路径算法。为什么会有这个博客?因为我发现当路径连接数量多了之后,许多模板类的方法就不好使了,而这个代码虽然使用了宏定义,但是超快同时保证结果正确!
#include <iostream>
#include <limits>
#include <vector>
using namespace std;
#define MAXV 10000
///计算路径并返回
void getPathList(int ptform,int ptend,std::vector<int>&pathList,int &distance);
class EdgeNode{
public:
int key;
int weight;
EdgeNode *next;
EdgeNode(int, int);
};
EdgeNode::EdgeNode(int key, int weight){
this->key = key;
this->weight = weight;
this->next = NULL;
}
class Graph{
bool directed;
public:
EdgeNode *edges[MAXV + 1];
Graph(bool);
~Graph();
void insert_edge(int, int, int, bool);
void print();
};
Graph::Graph(bool directed){
this->directed = directed;
for(int i = 1; i < (MAXV + 1); i ++){
this->edges[i] = NULL;
}
}
Graph::~Graph(){
//to do
}
void Graph::insert_edge(int x, int y, int weight, bool directed){
if(x > 0 && x < (MAXV + 1) && y > 0 && y < (MAXV + 1)){
EdgeNode *edge = new EdgeNode(y, weight);
edge->next = this->edges[x];
this->edges[x] = edge;
if(!directed){
insert_edge(y, x, weight, true);
}
}
}
void Graph::print(){
for(int v = 1; v < (MAXV + 1); v ++){
if(this->edges[v] != NULL){
cout << "Vertex " << v << " has neighbors: " << endl;
EdgeNode *curr = this->edges[v];
while(curr != NULL){
cout << curr->key << endl;
curr = curr->next;
}
}
}
}
void init_vars(bool discovered[], int distance[], int parent[]){
for(int i = 1; i < (MAXV + 1); i ++){
discovered[i] = false;
distance[i] = std::numeric_limits<int>::max();
parent[i] = -1;
}
}
void dijkstra_shortest_path(Graph *g, int parent[], int distance[], int start){
bool discovered[MAXV + 1];
EdgeNode *curr;
int v_curr;
int v_neighbor;
int weight;
int smallest_dist;
init_vars(discovered, distance, parent);
distance[start] = 0;
v_curr = start;
while(discovered[v_curr] == false){
discovered[v_curr] = true;
curr = g->edges[v_curr];
while(curr != NULL){
v_neighbor = curr->key;
weight = curr->weight;
if((distance[v_curr] + weight) < distance[v_neighbor]){
distance[v_neighbor] = distance[v_curr] + weight;
parent[v_neighbor] = v_curr;
}
curr = curr->next;
}
//set the next current vertex to the vertex with the smallest distance
smallest_dist = std::numeric_limits<int>::max();
for(int i = 1; i < (MAXV + 1); i ++){
if(!discovered[i] && (distance[i] < smallest_dist)){
v_curr = i;
smallest_dist = distance[i];
}
}
}
}
void print_shortest_path(int v, int parent[]){
if(v > 0 && v < (MAXV + 1) && parent[v] != -1){
cout << parent[v] << " ";
print_shortest_path(parent[v], parent);
}
}
///获取路径节点
void get_shortest_path(int v, int parent[],std::vector<int>&pathlist){
if(v > 0 && v < (MAXV + 1) && parent[v] != -1)
{
cout << parent[v] << " ";
pathlist.push_back(parent[v]);
get_shortest_path(parent[v], parent,pathlist);
}
}
int get_distances(int target, int distance[]){
if(target>MAXV||target<0){
cout << "目标地不存在!错误 ";
return 0;
}
if(distance[target] != std::numeric_limits<int>::max())
{
cout << "到达目标点 : "<<target<<" 距离:"<<distance[target];
return distance[target] ;
}
return 0;
}
void print_distances(int start, int distance[]){
for(int i = 1; i < (MAXV + 1); i ++){
if(distance[i] != std::numeric_limits<int>::max()){
cout << "Shortest distance from " << start << " to " << i << " is: " << distance[i] << endl;
}
}
}
void getPathList(int ptform,int ptend,std::vector<int>&pathList,int &distance)
{
}
int main(){
Graph *g = new Graph(false);
int parent[MAXV + 1];
int distance[MAXV + 1];
int start = 3482;
string dataFile="Linklines";
int count = 0;
FILE* pfData = fopen(dataFile.c_str(), "r");
if (pfData == NULL)
{
cout<<"DataFile does not exist!!!"<<endl;
return false;
}
else
{
int ptsid,pteid;
int weight;
while (!feof(pfData))
{
fscanf(pfData, "%d", &ptsid);
fscanf(pfData, "%d", &pteid);
fscanf(pfData, "%d", &weight);
g->insert_edge(ptsid, pteid, weight, false);
count++;
}
fclose(pfData);
std::cout<<" 读取树结构路径文件并构建成功! size:"<<count <<std::endl;
}
/* g->insert_edge(1, 2, 4, false);
g->insert_edge(1, 3, 1, false);
g->insert_edge(3, 2, 1, false);
g->insert_edge(3, 4, 5, false);
g->insert_edge(2, 4, 3, false);
g->insert_edge(2, 5, 1, false);
g->insert_edge(4, 5, 2, false);*/
dijkstra_shortest_path(g, parent, distance, start);
//print shortest path from vertex 1 to 5
print_shortest_path(3483, parent);
print_distances(start, distance);
delete g;
return 0;
}
啥?想看看效果?
给你个图瞅瞅!虽然两个方法都可以,但是你知道这里面的连接关系很复杂,例如里面节点数3842,连接关系18324个,这的多的连接关系,一般的模板算法计算失效。。。这个算法工作正常!
图1. Dijsk 算法寻路结果
图2 A*算法寻路结果