数据结构:单源最短路径--Dijkstra算法
来源:互联网 发布:mac玩qq堂 编辑:程序博客网 时间:2024/06/04 19:29
Dijkstra算法
单源最短路径
给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离。指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题。
Dijkstra算法
求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法。该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点。
算法思想
带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合。假设V0是源点,则初始 S={V0}。用数组Distance表示源点V0到其余顶点的路径长度,用数组pre[i]表示最短路径序列上顶点i的前一个顶点。初始时,pre[i]都是源点的下标。接下来需重复两个步骤:
- 从当前Distance[i]找出最小的一个,记录其下标v=i,源点V0到顶点Vv的最短路径即已确定,把Vv加入S。
- 更新源点到剩余顶点的最短路径长度。更新方法是:以上一步的顶点Vv为中间点,若Distance[v]+weight(v,i)<Distance[i],则修改值:pre[i]=v;Distance[i]=Distance[v]+weight(v,i);
需要指出,Dijkstra算法求解的不仅是有向图,无向图也是可以的。下面给出一个完整的有向带权图的实例:
实例
有向带权图
Dijkstra算法的求解过程
其中,INF是infinity无穷大的意思。
代码
类定义
- #include<iostream>
- #include<iomanip>
- #include<stack>
- using namespace std;
- #define MAXWEIGHT 100
- #ifdef INFINITY
- #undef INFINITY
- #endif
- #define INFINITY 1000
- class Graph
- {
- private:
- //顶点数
- int numV;
- //边数
- int numE;
- //邻接矩阵
- int **matrix;
- public:
- Graph(int numV);
- //建图
- void createGraph(int numE);
- //析构方法
- ~Graph();
- //迪杰斯特拉算法
- void Dijkstra(int);
- //打印邻接矩阵
- void printAdjacentMatrix();
- //检查输入
- bool check(int, int, int);
- };
- //构造函数,指定顶点数目
- Graph::Graph(int numV)
- {
- //对输入的顶点数进行检测
- while (numV <= 0)
- {
- cout << "顶点数有误!重新输入 ";
- cin >> numV;
- }
- this->numV = numV;
- //构建邻接矩阵,并初始化
- matrix = new int*[numV];
- int i, j;
- for (i = 0; i < numV; i++)
- matrix[i] = new int[numV];
- for (i = 0; i < numV; i++)
- for (j = 0; j < numV; j++)
- {
- if (i == j)
- matrix[i][i] = 0;
- else
- matrix[i][j] = INFINITY;
- }
- }
- void Graph::createGraph(int numE)
- {
- /*
- 对输入的边数做检测
- 一个numV个顶点的有向图,最多有numV*(numV - 1)条边
- */
- while (numE < 0 || numE > numV*(numV - 1))
- {
- cout << "边数有问题!重新输入 ";
- cin >> numE;
- }
- this->numE = numE;
- int tail, head, weight, i;
- i = 0;
- cout << "输入每条边的起点(弧尾)、终点(弧头)和权值" << endl;
- while (i < numE)
- {
- cin >> tail >> head >> weight;
- while (!check(tail, head, weight))
- {
- cout << "输入的边不正确!请重新输入 " << endl;
- cin >> tail >> head >> weight;
- }
- matrix[tail][head] = weight;
- i++;
- }
- }
- Graph::~Graph()
- {
- int i;
- for (i = 0; i < numV; i++)
- delete[] matrix[i];
- delete[]matrix;
- }
- /*
- 迪杰斯特拉算法
- 求指定顶点vertex到其它顶点的最短路径
- 不仅要得出最短路径长度,也要得到其序列
- */
- void Graph::Dijkstra(int vertex)
- {
- int i;
- //最短路径序列中每个顶点的直接前驱
- int *pre = new int[numV];
- for (i = 0; i < numV; i++)
- pre[i] = vertex;
- //顶点vertex到各个顶点的路径长度
- int *Distance = new int[numV];
- //初始化路径长度
- for (i = 0; i < numV; i++)
- Distance[i] = matrix[vertex][i];
- //标记各个顶点最短路径找到与否
- bool *find = new bool[numV];
- memset(find, 0, numV);
- find[vertex] = true;
- int d, v, count;
- count = 1, v = vertex;
- while (count < numV)
- {
- d = INFINITY;
- //确定一个最短距离
- for (i = 0; i < numV; i++)
- {
- if (!find[i] && Distance[i] < d)
- {
- d = Distance[i];
- v = i;
- }
- }
- find[v] = true;
- //更新剩余顶点的前驱和最短距离
- for (i = 0; i < numV; i++)
- {
- if (!find[i])
- {
- d = Distance[v] + matrix[v][i];
- if (d < Distance[i])
- {
- pre[i] = v;
- Distance[i] = d;
- }
- }
- }
- count++;
- }
- //打印最短路径序列和其长度
- stack<int> s;
- for (i = 0; i < numV; i++)
- {
- if (Distance[i] == 0);
- else if (Distance[i] == INFINITY)
- cout << "顶点 " << vertex <<" 到顶点 " << i <<" 无路径!" << endl;
- else
- {
- cout << "顶点 " << vertex << " 到顶点 " << i
- << " 最短路径长度是 " << Distance[i]
- << " ,其序列是...";
- v = i;
- s.push(v);
- do
- {
- v = pre[v];
- s.push(v);
- } while (v!=vertex);
- //打印最短路径序列
- while (!s.empty())
- {
- cout << setw(3) << s.top();
- s.pop();
- }
- cout << endl;
- }
- }
- cout << endl;
- delete[]find;
- delete[]pre;
- delete[]Distance;
- }
- //打印邻接矩阵
- void Graph::printAdjacentMatrix()
- {
- int i, j;
- cout.setf(ios::left);
- cout << setw(7) << " ";
- for (i = 0; i < numV; i++)
- cout << setw(7) << i;
- cout << endl;
- for (i = 0; i < numV; i++)
- {
- cout << setw(7) << i;
- for (j = 0; j < numV; j++)
- cout << setw(7) << matrix[i][j];
- cout << endl;
- }
- }
- bool Graph::check(int tail, int head, int weight)
- {
- if (tail < 0 || tail >= numV || head < 0 || head >= numV
- || weight <= 0 || weight >= MAXWEIGHT)
- return false;
- return true;
- }
- int main()
- {
- cout << "******Dijkstra***by David***" << endl;
- int numV, numE;
- cout << "建图..." << endl;
- cout << "输入顶点数 ";
- cin >> numV;
- Graph graph(numV);
- cout << "输入边数 ";
- cin >> numE;
- graph.createGraph(numE);
- cout << endl << "Dijkstra..." << endl;
- for (int i = 0; i < numV; i++)
- graph.Dijkstra(i);
- system("pause");
- return 0;
- }
完整代码下载:Dijkstra算法
转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38360337
若有所帮助,顶一个哦!
专栏目录:
- 数据结构与算法
- c指针
阅读全文
0 0
- 数据结构----dijkstra算法,单源最短路径
- 数据结构:单源最短路径--Dijkstra算法
- 数据结构:单源最短路径--Dijkstra算法
- 算法与数据结构-单源最短路径之Dijkstra
- [数据结构]Dijkstra算法求单源最短路径
- 数据结构与算法12:单源最短路径Dijkstra算法
- 单源最短路径 dijkstra算法
- 单源最短路径Dijkstra算法
- Dijkstra 单源最短路径算法
- 单源最短路径 :Dijkstra 算法
- 单源最短路径(Dijkstra算法)
- 单源最短路径----------Dijkstra算法
- 单源最短路径Dijkstra算法
- 单源最短路径(Dijkstra算法)
- 单源最短路径 : Dijkstra 算法
- Dijkstra单源最短路径算法
- 算法 单源最短路径Dijkstra
- 单源最短路径-Dijkstra算法
- JAVA-WEB Hibernate面试整理
- 结构体及位段
- 三极管基极偏置电路原理应用于继电器的驱动电路的分析
- Markdown
- go语言使用redis —— redigo
- 数据结构:单源最短路径--Dijkstra算法
- JSP内置对象和EL内置对象及区别解析
- 高级数据结构及算法分类
- CreateProcess 创建带命令行参数的进程时,报错或者提示内存位置无效的可能的一个原因
- 抽象类
- Android MVP(Model View Presenter)
- Java1.8源码阅读-DualPivotQuicksort
- delphi 身份证号码相关处理单元
- 四叉树-2D平面的渲染剔除、碰撞次数优化