Dijkstra算法
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
问题描述: 在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
原理
Dijkstra是贪心算法(每次都想取目前的最优),从出发点开始,它每次从不在最短路径树上的点集合中寻找最近的点,将其加入最短路径树,并从该点更新起点到它的邻接边的距离,直到遍历完所有点或遇到目的地。
选取A作为起点,path为到达该节点的路径的前一个节点的下标,dist表示起点到该节点的距离,
visited表示该节点是否被访问,将dist初始化为起点到该节点的权值,不可达的表示为∞,将path对应dist不为无穷的更新为起点,其余为-1
从visited中未访问过的节点中选取dist最小的节点2
将2其标记为已访问,然后将2可到达的节点的dist值进行更新,如果dist[2]+arc[2][i] (将2作为中继站)<dist[i],则进行更新,并将path[i]修改为2,重复以上步骤
想要找到起点到某点的最短路径,则从path中找到该点对应的path[i],再查找下标path[i]对应的值,直到下标与值相等
const int MAXSIZE = 100;
#define inf 0x3f3f3f3f
void Disjkstra(int start)
{
int dist[MAXSIZE];
int path[MAXSIZE];
bool visited[MAXSIZE] = { 0 };
//初始化
visited[start] = 1;//1表示v已在集合中
for (int i = 0; i < vertexNum; i++)
{
dist[i] = arc[start][i];
if (dist[i] != inf)
path[i] = start;
else path[i] = -1;
}
for (int i = 0; i < vertexNum; i++)
{
int min = inf;
int k = 1;
int j = 0;
//查找未访问集合中最小dist对应的下标
while (j < vertexNum)
{
if (visited[j] == 0 && dist[j] < min)
{
min = dist[j];
k = j;
}
j++;
}
visited[k] = 1;
//更新dist和path
for (int i = 0; i < vertexNum; i++)
{
if (visited[i] == 0 && (dist[i] > min + arc[k][i]))
{
dist[i] = min + arc[k][i];
path[i] = k;
}
}
}
for (int i = 0; i < vertexNum; i++)
{
if (i == start)
continue;
cout << "从" << vertex[start] << "到" << vertex[i] << "的最短路径为:" ;
int temp = i;
stack st;
st.push(temp);
while (temp != start)
{
temp = path[temp];
st.push(temp);
}
while (!st.empty())
{
int x = st.top();
st.pop();
cout << vertex[x] << " ";
}
cout << "路径长度为" << dist[i];
cout << endl;
}
}