天天看点

最短路径算法介绍

这里不说废话,直接看代码,实现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*算法寻路结果