叙述
今天终于写到著名的贪心算法——Dijkstra算法了,内心有点激动。
-
小明的故事
Dijstra算法对很多人来说看起来比较困难,不是很能理解,其实也没什么啦!
比如,小明要自己驾车从科技大学去博物馆,考虑到利益上涨油价以及一贫如洗的口袋,小明不能那么任性,来一场说走就走的旅行,所以小明开始像屌丝一样精打细算,寻找一条最短的路径以结束那些不必要的花费。你掏出地图,认真的比较到博物馆去的各种路线,但及其复杂的路网让小明眼花缭乱,一时半会找不到最节省的路线,内心很是烦躁,此时此刻小明掏出口袋里的白将军,狠狠地吸上一口,突然一道光从脑子里闪出来,很快就找到了最短路径。
-
小明是怎么实现的呢?
小明想我能不能先找到距离科技大学最近的地标,然后再以这个地标为起点,寻找下一个距离最近的地标,循序渐进,直到找到目的地。因为每次找到的距离都是最近的,所以从始发地到目的地累加起来的距离也是最近的。果然是一个好主意,激动的小明把没抽完的半根白将军狠狠的扔在地上,并用脚摩擦了几下,开始寻找最短路径,很快就找了理想的路线。 -
小明的灿烂人生
计算机出身的小明回去以后很快发现了商机,通过自己的聪明才智,开发出了地图软件,挣了好大一笔钱,并用这笔钱投资了国内最大的单身交友平台—CSDN,成为了CSDN的老板,过上了幸福美满的生活。
代码实现:
/*
Dijkstra的思路就是:
找到与源点权值最小的边,然后再此边找到到其他顶点的最小的边,依次类推,每次找到的都是最小的边
最后所得的最短路径长度就是各最小边的和
*/
#include<iostream>
#include<string>
#include<stack>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXint 32767 //表示无穷大
#define MVNum 100 //最大顶点数
//邻接矩阵的结构
typedef struct
{
string vexs[MVNum];//顶点表
int arcs[MVNum][MVNum];//邻接矩阵,也就是表示边的权值
int vexnum, arcnum;//图的顶点数和边的个数
}AMGraph;
//邻接矩阵的结构
//Dijstra结构
bool S[MVNum] = {
false };//记录从源点到终点是否已被确定最短路径长度
int Path[MVNum] = {
-1 };//记录终点的直接前驱序号
int D[MVNum];//记录最短路径长度
//Dijstra结构
//查询结点位置
int Locate(AMGraph G, string v)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.vexs[i] == v)
{
return i;
}
}
return -1;
}
//查询结点位置
//创建邻接矩阵
int CreateUDN(AMGraph& G)//无向图的构造
{
cout << "请输入图的顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入各点的信息:";
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.vexs[i];
}
for (int i = 0; i < G.vexnum; i++)//初始化边的权值为MAXINT
{
for (int j = 0; j < G.vexnum; j++)
{
G.arcs[i][j] = MAXint;
}
}
cout << "各边的顶点信息和权值:";
for (int k = 0; k < G.arcnum; k++)//构造邻接矩阵
{
string v1, v2;
int w;//边的两个顶点以及权值
cin >> v1 >> v2 >> w;
int i = Locate(G, v1);//找到点的位置
int j = Locate(G, v2);
G.arcs[i][j] = w;//赋予权值
//G.arcs[j][i] = G.arcs[i][j];
}
return OK;
}
//创建邻接矩阵
//Dijksta
void ShortestPath_DIJ(AMGraph G, int v)
{
int n = G.vexnum;//图的节点的数量
for (int i = 0; i < n; i++)
{
D[i] = G.arcs[v][i];
if (D[i] < MAXint)
{
Path[i] = v;
}
else
{
Path[i] = -1;
}
}
S[v] = true;//初始化v已有最短路径
D[v] = 0;//最短路径为0
for (int i = 1; i < n; i++)
{
int min = MAXint;
for (int j = 0; j < n; j++)//找到与v邻接的边的权值最小的
{
if (!S[j] && D[j] < min)
{
v = j;
min = D[j];
}
}
S[v] = true;//找到最短路径
for (int k = 0; k < n; k++)//更新从v出发到各顶点的最短路径长度
{
if (!S[k] && (D[v] + G.arcs[v][k]) < D[k])
{
D[k] = D[v] + G.arcs[v][k];//更新最短路径长度
Path[k] = v;//更改k的前驱为v
}
}
}
}
//Dijksta
//显示最短路径
void ShowShortTest(AMGraph G, string v)
{
int s = Locate(G,v);//定位
ShortestPath_DIJ(G, s);
for (int i = 0; i < G.vexnum; i++)
{
stack<string> sta;//引入栈
if (i != s && Path[i] != -1)
{
sta.push(G.vexs[i]);
int path = Path[i];
while (path != -1)
{
sta.push(G.vexs[path]);
path = Path[path];
}
}
if (!sta.empty())
{
cout << sta.top();
sta.pop();
}
while (!sta.empty())
{
cout << "->";
cout << sta.top();
sta.pop();
}
if (i != s && Path[i] != -1)
{
cout << " 最短路径长度为:" << D[i];
cout << endl;
}
}
}
//显示最短路径
int main()
{
AMGraph G;
CreateUDN(G);
string v;
cout << "请输入起点:";
cin >> v;
ShowShortTest(G, v);
return 0;
}
/*
v0 v1 v2 v3 v4 v5
各边的顶点信息和权值:v1 v2 5 v2 v3 50 v0 v2 10 v0 v4 30 v4 v3 20 v3 v5 10 v0 v5 100 v4 v5 60
*/