如上有向无权图:总共7个顶点12条边
如果以顶点3开始,那么它对应的去每个顶点的路径应该是:
顶点1 3->1 | 1 |
顶点2 3->1->2 | 2 |
顶点3 3->3 | 0 |
顶点4 3->1->4 | 2 |
顶点5 3->1->2->5 | 3 |
顶点6 6->3 | 1 |
顶点7 3->1->4->7 | 3 |
这里用到的算法与BFS类似;还是需要一个队列(出队入队操作)
typedef struct node{
int date[MAX];
int tail;
int head;
}Quque;
void add(int x,Quque *Q)//入队
{
Q->date[Q->tail++]=x;
}
int isEmpty(Quque *Q) //是否非空?
{
if(Q->head>=Q->tail)
return 1;
else
return 0;
}
int delet(Quque *Q)//出队
{
int x=Q->date[Q->head];
Q->head++;
return x;
}
然后需要两个数组,不同于BFS(visit数组),这里用了一个dist[] (记录路径长度,初始化-1)和一个path[](记录来时走过的路)
int dist[110];
int path[110];
for(i=0;i<110;i++)//初始化为-1
dist[i]=-1;
for(i=0;i<110;i++)//初始化为-1
path[i]=-1;
当要寻找最短路径的源头为i时,dist[i]=0;(自己到自己长度为0)
void unweighted(int i,Quque *Q)
{
add(i,Q);//将顶点i入队
while(!isEmpty(Q)) //当队列非空
{
int j,t=delet(Q);//令t=出队
for(j=1;j<=N;j++)//遍历所有顶点
{
if(a[t][j]==1&&dist[j]==-1)//如果出队的顶点t还有其他边 并且没访问过(路径等于-1)
{
dist[j]=dist[t]+1;//路径+1
path[j]=t; //记录上一个路径
add(j,Q);//将该顶点入队
}
}
}
}
完整代码测试:
//无权图单源最短路径
#include<stdio.h>
#include<stdlib.h>
#define MAX 110
int N;
int E;
int a[10][10];
int dist[110];
int path[110];
int way[110];
typedef struct node{
int date[MAX];
int tail;
int head;
}Quque;
void add(int x,Quque *Q);
int isEmpty(Quque *Q);
int delet(Quque *Q);
void unweighted(int i,Quque *Q);
int main()
{
int i,x1,x2;
for(i=0;i<110;i++)
dist[i]=-1;
for(i=0;i<110;i++)
path[i]=-1;
scanf("%d%d",&N,&E);
for(i=0;i<E;i++)
{
scanf("%d%d",&x1,&x2);
a[x1][x2]=1;
}
Quque *Q=(Quque*)malloc(sizeof(Quque));
Q->head=Q->tail=0;
dist[3]=0;//顶点设为3 初始化为0
unweighted(3,Q);
for(i=1;i<=N;i++)
{
printf("顶点3到顶点%d的路径长度:%d\n",i,dist[i]); //输出每个顶点到3的最短路径
int t=i;
int cnt=0;
way[cnt]=3;
printf("路径%d",way[cnt]);
while(path[t]!=-1)
{
way[cnt++]=t;
t=path[t];
}
while(cnt--) printf("->%d",way[cnt]);
printf("\n");
}
return 0;
}
void add(int x,Quque *Q)
{
Q->date[Q->tail++]=x;
}
int isEmpty(Quque *Q)
{
if(Q->head>=Q->tail)
return 1;
else
return 0;
}
int delet(Quque *Q)
{
int x=Q->date[Q->head];
Q->head++;
return x;
}
void unweighted(int i,Quque *Q)
{
add(i,Q);//将顶点i入队
while(!isEmpty(Q)) //当队列非空
{
int j,t=delet(Q);//令t=出队
for(j=1;j<=N;j++)//遍历所有顶点
{
if(a[t][j]==1&&dist[j]==-1)//如果出队的顶点t还有其他边 并且没访问过(路径等于-1)
{
dist[j]=dist[t]+1;//路径+1
path[j]=t; //记录上一个路径
add(j,Q);//将该顶点入队
}
}
}
}
最后输出: