Dijkstra算法最初用于搜索一个正加权连通图中两顶点(起始点, 终点)之间最短路径。 它由Edsger W. Dijkstra 在1956设计,并于三年后发表[wiki].
Dijkstra[3]
算法核心思想
将图中顶点分为两个集合,一个集合 S S S包含已搜索过的顶点; 另一个集合 S ∗ S^{*} S∗是 S S S的补集, 包含未搜索过的顶点.
以顶点到起始点之间最短路径为度量,为 S S S中各顶点赋值.
基于 S S S边界逐步向 S ∗ S^{*} S∗扩展, 直到搜索到终点为止.
Dijkstra算法适用范围
- 连通图。
- 图中边的加权值应为正数。
算法实现
Dijkstra算法的实现需要两种容器类数据结构: 一个是维护图信息,另一个保存路径信息. Dijkstra算法所需的图操作有:
- 添加顶点,添加边,
- 设置边的权值,
- 提取顶点,
- 遍历与某个顶点相连的边和顶点.
代码
Rosetta提供了一个C语言版的Dijkstra算法代码[Rosetta]. 现将其改写成C++版, 代码如下:
dijkstra.h
#ifndef YANG_A_GRAPH_DIJK_H_
#define YANG_A_GRAPH_DIJK_H_
/*
* dijkstra.h
*
* Created on:
* Author:
* Based on:
* https://rosettacode.org/wiki/Dijkstra%27s_algorithm
*
* Copyright @ 2017. CHUNFENG YANG. All Rights Reserved.
* Permission to use, copy, modify, and distribute this software
* and its documentation for educational, research, and
* not-for-profit purposes, without fee and without a signed
* above copyright notice, this paragraph and the following two
* distributions.
* IN NO EVENT SHALL CHUNFENG YANG BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
* DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS
* SOFTWARE AND ITS DOCUMENTATION, EVEN IF CHUNFENG YANG HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* CHUNFENG YANG SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS
* PROVIDED "AS IS". CHUNFENG YANG HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
class Edge
{
public:
Edge();
virtual ~Edge();
public:
void show();
public:
int _vertex;
double _weight;
};
class Vertex
{
public:
Vertex();
virtual ~Vertex();
public:
void addEdge(Edge*);
void setDist(double);
double getDist();
void setPrev(int);
int getPrev();
void setVisited(int);
int getVisited();
int edgeLength();
Edge* getEdge(int);
void show();
public:
Edge **_edges;
int _edges_len;
int _edges_size;
double _dist;
int _prev;
int _visited;
};
class Heap
{
public:
Heap();
Heap(int n);
virtual ~Heap();
public:
void push(int v, double p);
int pop();
int minimize(int i, int j, int k);
int length();
void show();
void clean();
public:
int *_data;
double *_prio;
int *_index;
int _len;
int _size;
};
class Graph
{
public:
Graph();
virtual ~Graph();
Graph(int);
public:
void addVertex(int i);
void addEdge(int a, int b, double w);
void dijkstra(int a, int b);
void print_path(int);
void show();
double distance(int i, int j);
int length();
public:
Vertex **_vertices;
int _vertices_len;
int _vertices_size;
};
#endif // YANG_A_GRAPH_DIJK_H_
dijkstra.cc
/*
* dijkstra.cc
*
* Created on:
* Author:
* Based on:
* https://rosettacode.org/wiki/Dijkstra%27s_algorithm
*
* Copyright @ 2017. CHUNFENG YANG. All Rights Reserved.
* Permission to use, copy, modify, and distribute this software
* and its documentation for educational, research, and
* not-for-profit purposes, without fee and without a signed
* above copyright notice, this paragraph and the following two
* distributions.
* IN NO EVENT SHALL CHUNFENG YANG BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCID