最短路径问题与现实生活中的问题息息相关,所以最短路径问题一定要掌握,这是书上的介绍
怎么理解呢?还是给个例子会比较清楚,比如下面这个图:
初始时,集合s={a}(假设a为源点),t={b,c,d,e}
然后从t中选取到a路径长度最短的顶点:
a-b ->6
a-c ->2
a-d ->无穷大(a和d之间不能直接连接)
a-e ->无穷大
可以看到,a-c路径最短,所以选取c到s中,a-c路径记录下来
s={a,c},t={b,d,e}
现在比较 “原来t中b,d,e各点的最短路径长度” 和 ”通过上次记录下来的路径再到达各点的路径长度",
a-b ->6 < a-c-b -> 无穷大
//所以当前a到b的最短路径为a-b ->6
a-d ->无穷大 > a-c-d -> 3
//所以当前a-d的最短路径为a-c-d ->3
a-e->无穷大 > a-c-e ->9
//所以当前a-e的最短路径为a-c-e ->9
现在t中a-c-d 路径最短,将d选进s
s={a,c,d} t={b,e}
a-b ->6 > a-c-d-b ->5
//所以当前a到b的最短路径为a-c-d-b ->6
a-c-e ->9 < a-c-d-e
//所以当前a-e的最短路径为a-c-e ->9
现在t中a-c-d-b路径最短,将b选进s
s={a,c,d,b},t={e}
a-c-e ->9 < a-c-d-b-e ->13
//所以当前a-e的最短路径为a-c-e ->9
将e选进s,s={a,b,c,d,e}现在图中所有顶点都在s中,算法结束
已上就是Dijkstra算法的一个具体例子,应该很明白了,那就实现它吧
dijkstra成员函数
void adjaMultiList::dijkstra(int v0)//显示v0到其他各点的最短路径
{
//构造两个集合S和U,S保存已经找到的最短路径的点,U保存还未找到的点,初始时 S只有V0,S
//为剩余的所有点,不妨用vector来表示路径,比如路径0-1-2,,vector相应的就包含3个元素,0,1,2
map<int, vector<int>> path;//第一个表示某顶点编号,第二个表示v0到该顶点的路径
vector<int> s = { v0 };//初始时s中只有v0
vector<int> u;//初始时u中为剩下所有点
for (int i = 0; i < iVertex - 1; ++i)
{
if (i < v0)
u.push_back(i);
else u.push_back(i + 1);
}
vector<int> u1 = u;
vector<double> path_weight;
for (int i1 = 0; i1 < iVertex; ++i1)
path_weight.push_back(0);
//vector<double> path_weight1;//保存最终的最短路径长度
int selected=v0;//每次循环后选进s的点,初始时从v0开始
int u_size = iVertex - 1;//初始时u中顶点个数总个数减1
int s_size = 1;//初始时s中顶点个数为1
double min;
vector<int> selectedMinPath;
for (int i = 0; i < iVertex - 1; ++i)
{
for (int k = 0; k<u_size; ++k)
{
if (i == 0)//第一次循环
{
path_weight[u[k]]=getWeight(v0,u[k]);
path[u[k]].push_back(v0);
path[u[k]].push_back(u[k]);
}
else
{
//如果从之前选中的顶点那条路径距离加上再走向某点的距离小于原来的距离,更新
if (min + getWeight(selected, u[k])<path_weight[u[k]])
{
path[u[k]] = selectedMinPath;
path[u[k]].push_back(u[k]);
path_weight[u[k]] = min + getWeight(selected, u[k]);
}
}
}
//选取u中路径长度最小的,min为最小路径长度,selectedMinPath为最小路径,num为选中的顶点
min = path_weight[u[0]];
int num = u[0];//v0到某点的路径最短,u为该点编号
int m = 1;
for (; m < u_size; ++m)
{
if (min > path_weight[u[m]])
{
min = path_weight[u[m]];
num = u[m];
}
}
selected = num;
selectedMinPath = path[num];
++s_size;
s.push_back(num);
--u_size;
//删除u中编号为num的顶点
for (vector<int>::iterator it = u.begin(); it != u.end(); ++it)
{
if (*it == num)
{
u.erase(it);
break;
}
}
}
cout << "顶点" << vertexElem[v0].data << "到其他各顶点的最短路径及长度分别为:" << endl;
for (int i2 = 0; i2 < iVertex - 1; i2++)
{
cout << vertexElem[u1[i2]].data << ": 长度:"<<path_weight[u1[i2]]<<" 路径:";
for (auto it = path[u1[i2]].begin(); it != path[u1[i2]].end(); ++it)
cout << vertexElem[*it].data << "-";
cout << "\b "<<endl;//注意加个空格,相当于光标定位到前一个,然后写入空格代替了-
}
}
换个开始点,比如换成D看看