您的位置:首页 > 其它

图的更多相关算法-2(最短路径)

2013-04-22 14:26 232 查看
void DispPath(int path[],int begin, int end)               //此函数是输出从begin节点到end节点最短的路径
{
int ivar = 0;
ivar = path[end];
cout<<"path is :"<<end<<' ';
while(ivar != 0)
{
cout<<ivar<<' ';
ivar = path[ivar];
}
cout<<begin<<endl;
}

/*
此算法求节点距离其他节点的最短距离
s[i] == 1数组表示节点i在 s中不再 U中
dist[i]数组保存从begin到i节点的路径最小值
path[i]数组保存的是路径中在i节点前面的节点的值
思路:
在dist数组中查找在s数组中最短的路径的值,把找到的节点当做中间节点, 如果通过中间节点的路径比直达的路径或原先的路径短就进行替换
整个查找中间节点的操作是在dist数组中进行的

此算法与普利姆算法的区别是当找到中间节点后,此算法会由中间节点计算权的值,并进行相关的计算
而普利姆算法则是利用中间的修正候选边

普利姆算法中的lowcost保存的是两个顶点之间的最短路径
而狄更拉斯算法中的  dist数组保存的是初始顶点到其他顶点之间的最短路径,中间可以有节点存在即不是直达的节点
*/
void Dijkstra(MGraph mg, int begin)
{
int loop1 = 0, count = 0, min = 1000, node = 0, path[MAXSIZE]; //path[i] 保存的是从begin 到i的路径中,位于 i前面的一个节点的值
int s[MAXSIZE], dist[MAXSIZE];                              //s数组用以说明顶点的位置,当s[i] == 1的时候,说明顶点i在s中, 当s[i] == 0 的时候说明顶点在U中
//dist[i]数组用以保存从顶点begin 到 顶点为i的最短距离
for(loop1 = 0; loop1 < MAXSIZE; ++loop1)
s[loop1] = 0;
s[begin] = 1;

for(loop1 = 0; loop1 < mg.n; ++loop1)
{
dist[loop1] = mg.edges[begin][loop1];                   //dist[i] == 0的话,表示从 顶点begin 到 i节点不可到达
if(mg.edges[begin][loop1] == 0)                         //此处为path赋初值,如果begin到节点loop1可直达,则path为0 代表这个路径的前一个节点是begin节点本身, 否则的话path初始化为-1 ,代表没有路径
{   path[count] = -1; ++count; }
else
{   path[count] =  0; ++count; }
}
path[begin] = 0;
count = 1;

while(count < mg.n)
{
min = 1000;
for(loop1 = 0; loop1 < mg.n; ++loop1)               //此处进行查找最短的路径,条件是节点在U中,并且从begin到节点必须可以到达
{
if(s[loop1] == 0 && dist[loop1] != 0 && min > dist[loop1])
{
min  = dist[loop1];
node = loop1;
}
}
cout<<"Visiting node  "<<node<<endl;

s[node] = 1;                                        //node为找到的节点
for(loop1 = 1; loop1 < mg.n; ++loop1)               //此步骤是以找到的node节点为点,循环遍历与node直接相邻的量
{
if(node != loop1 && mg.edges[node][loop1] != 0)//条件是不遍历自己, 并且那个节点与node节点应该可直达
{
if(dist[loop1] == 0  )                     //此处表示如果begin节点到loop1节点不能直达的话,就直接把经过node节点的距离当做最短距离
{   dist[loop1] = dist[node] + mg.edges[node][loop1];  path[loop1] = node;}
else if((dist[node] + mg.edges[node][loop1] ) < dist[loop1])        //否则的话,就进行判断如果进过node节点的路径长度小于直达的路径长度,进把距离的值重新赋值
{   dist[loop1] = dist[node] + mg.edges[node][loop1];  path[loop1] = node;}
}
}
++count;
}

for(loop1 = 0; loop1 < mg.n; ++loop1)
{
cout<<"shortest path to "<<loop1<<" is "<<dist[loop1]<<endl;
}
DispPath(path,begin,6);
}

/*
采用弗洛伊德算法求每对顶点之间的最短路径
A[i][j]数组用以保存从i节点到j节点之间的最短路径,初始的值为顶点之间的权值
path[i][j]数组用以保存上一个节点的编号,即中间节点的编号,初始化的值为-1,表示没有中间节点

其步骤是:
1. 确定顶点i到j之间是否有通过0节点的路径,如果有的话,此时表示A[i][0] != 0  A[0][j] != 0 成立,然后判断这两段的长度是否比直达的长度小,如果小的话,就进行最短路径的替换(A数组保存的最短的路径),同时把path数组相应的节点置为0,表示从节点i到节点j之间存在一个中间节点为0
2. 考察顶点i到j之间是否有通过1节点的路径,如果有的话,即按照上面的步骤进行,否则直接跳过
3. 重复上述步骤2

通过比较知道:狄克斯特拉算法是求某个特定的顶点到其余顶点之间的最短路径    此算法表现的是特定的顶点与其余顶点之间的关系
而弗洛伊德算法则是求每对顶点之间的最短路径                   此算法表现的是定点与顶点的关系
*/

void Floyd(MGraph mg)
{
int path[MAXSIZE][MAXSIZE], A[MAXSIZE][MAXSIZE];        //path[i][j]数组保存的是从顶点i到顶点j中间节点编号不大于k的路径的上一个节点的编号
int ivar = mg.n, loop1 = 0, loop2 = 0, loop3 = 0;                                                             //A[i][j]数组保存的是从i到j的最短距离

for(loop1 = 0; loop1 < ivar; ++loop1)
for(loop2 = 0; loop2 < ivar; ++loop2)
{
path[loop1][loop2] = -1;
A[loop1][loop2]    = mg.edges[loop1][loop2];                          //对A数组进行初始化为边的权值,0表示两个顶点之间不可以直达或没路径
}

for(loop1 = 0; loop1 < ivar; ++loop1)
{   for(loop2 = 0; loop2 < ivar; ++loop2)
for(loop3 = 0; loop3 < ivar; ++loop3)
{//此处应该以A数组为对象,不应该以mg.edges数组为对象。
//  if(loop2 != loop3 && mg.edges[loop2][loop1] != 0 && mg.edges[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (mg.edges[loop2][loop1] + mg.edges[loop1][loop3]) < A[loop2][loop3]))
if(loop2 != loop3 && A[loop2][loop1] != 0 && A[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (A[loop2][loop1] + A[loop1][loop3]) < A[loop2][loop3]))
{
A[loop2][loop3]    = A[loop2][loop1] + A[loop1][loop3];
path[loop2][loop3] = loop1;
}
}
for(loop2 = 0; loop2 < ivar; ++loop2)
{   for(loop3 = 0; loop3 < ivar; ++loop3)
cout<<A[loop2][loop3]<<' ';
cout<<endl;
}
cout<<endl;
}
}

void MinTree(MGraph mg,int begin)
{
int dist[MAXSIZE], path[MAXSIZE], v[MAXSIZE];
int loop1 = 0, count = 1,node = 0, min = 10000, pre = 0,ivar = mg.n;

for(loop1 = 0; loop1 < ivar; ++loop1)
{
v[loop1]    = 0;
dist[loop1] = mg.edges[begin][loop1];
if(mg.edges[begin][loop1] != 0)
{ path[loop1] = begin; }
else
{ path[loop1] = -1; }
}

v[begin] = 1;
count    = 1;
while(count < ivar)
{
min = 10000;
for(loop1 = 0; loop1 < ivar; ++loop1)
{
if(v[loop1] == 0 && dist[loop1] != 0 && min > dist[loop1])
{
node = loop1;
min  = dist[loop1];
}
}
v[node] = 1;
for(loop1 = 0; loop1 < ivar; ++loop1)
{
if(mg.edges[node][loop1] != 0 && (dist[loop1] == 0 || (dist[node] + mg.edges[node][loop1]) < dist[loop1] ))
{
dist[loop1] = mg.edges[node][loop1]  + dist[node];
path[loop1] = node;
}
}
++count;
}

for(loop1 = 0; loop1 < ivar; ++loop1)
{
if(v[loop1] == 1 && loop1 != begin)
{
pre = path[loop1];
cout<<"line is "<<pre<<" to "<<loop1<<" weight is "<<mg.edges[pre][loop1]<<endl;
}
}
}

void Centerp(MGraph mg)
{
int loop1 = 0, loop2 = 0, loop3 = 0, max = -1, maxindex = 0, ivar = mg.n;
int A[MAXSIZE][MAXSIZE], path[MAXSIZE][MAXSIZE];

for(loop1 = 0; loop1 < ivar; ++loop1)
for(loop2 = 0; loop2 < ivar; ++loop2)
{
A[loop1][loop2]    = mg.edges[loop1][loop2];
path[loop1][loop2] = -1;
}
for(loop1 = 0; loop1 < ivar; ++loop1)
for(loop2 = 0; loop2 < ivar; ++loop2)
for(loop3 = 0; loop3 < ivar; ++loop3)
{
if(A[loop2][loop1] != 0 && A[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (A[loop2][loop1] + A[loop1][loop3]) < A[loop2][loop3]) )
{
A[loop2][loop3]    = A[loop2][loop1] + A[loop1][loop2];
path[loop2][loop3] = loop1;
}
}
for(loop1 = 0; loop1 < ivar; ++loop1)
{
for(loop2 = 0; loop2 < ivar; ++loop2)
{
if(max < A[loop2][loop1])
{
max      = A[loop2][loop1];
maxindex = loop1;
}
}
}
cout<<"the center node is : "<<maxindex<<endl;
}


本文出自 “赛” 博客,请务必保留此出处http://saibro.blog.51cto.com/2052408/1183644
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: