设计算法求出无向连通区图中距离顶点v0的最短路径长度(最短路径长度以边数为单位计算)为K的所有顶点,要求尽可能的节省时间。
【分析】这是西北大学考研试题。本题应用广度优先遍历求解,若以v0作为生成树的根为第1层,则距离顶点v0最短路径长度为K的顶点均在第K+1层。可用队列存放顶点,将遍历访问顶点的操作改为入队操作。队列中设头尾指针分别为f和r,用level表示层数。
主要考查图的遍历。可以采用图的广度优先遍历,找出第K层的所有的顶点,例如,一个无向图如下图所示,图中有8个顶点和9条边。
算法思想:利用广度优先遍历对图进行遍历,从v0开始,依次访问与v0相邻接的各个顶点,利用一个队列存储所有已经访问过的顶点和该顶点与v0的最短路径,并将该顶点的标志位置为1表示已经访问过。依次取出队列的各个顶点,如果该顶点存在未访问过的邻接点,首先判断该顶点是否距离v0的最短路径为K,如果满足条件将该邻接点输出,否则将该邻接点入队,并将距离v0的层次加1。重复执行上述操作,直到队列为空或者存在满足条件的顶点为止。
code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef char VertexType[4];
typedef char InfoPtr;
typedef int VRType;
#define MAXSIZE 100
typedef enum
{
DG,DN,UG,UN
}GrapgKind;
typedef struct ArcNode
{
int adjvex;
InfoPtr *info;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
VertexType data;
ArcNode *firstarc;
}VNode,AdjList[MAXSIZE];
typedef struct
{
AdjList vertex;
int vexnum, arcnum;
GrapgKind kind;
}AdjGraph;
void BsfLevel(AdjGraph G, int v0, int k)
{
int visited[MAXSIZE];
int queue[MAXSIZE][2];
int front = 0, rear = -1, v, i, level, yes = 0;
ArcNode *p;
for (i = 0; i < G.vexnum;i++)
{
visited[i] = 0;
}
rear = (rear + 1) % MAXSIZE;
queue[rear][0] = v0;
queue[rear][1] = 1;
visited[v0] = 1;
level = 1;
do
{
v = queue[front][0];
level = queue[front][1];
front = (front + 1) % MAXSIZE;
p = G.vertex[v].firstarc;
while (p!=NULL)
{
if (visited[p->adjvex]==0)
{
if (level==k)
{
if (yes == 0)
{
cout << "距离" << G.vertex[v0].data << "最短的路径为" << k << "的顶点有:" << G.vertex[p->adjvex].data;
}
else
{
cout << " ," << G.vertex[p->adjvex].data;
}
yes = 1;
}
visited[p->adjvex] = 1;
rear = (rear + 1) % MAXSIZE;
queue[rear][0] = p->adjvex;
queue[rear][1] = level + 1;
}
p = p->nextarc;
}
} while (front != rear&&level < k + 1);
cout << endl;
}
void DisplayGraph(AdjGraph G)
{
int i;
ArcNode *p;
cout << G.vexnum << "个顶点:" << endl;
for (i = 0; i < G.vexnum; i++)
{
cout << G.vertex[i].data << " ";
}
cout << G.arcnum << "条边:" << endl;
for (i = 0; i < G.vexnum; i++)
{
p = G.vertex[i].firstarc;
while (p)
{
cout << G.vertex[i].data << "->" << G.vertex[p->adjvex].data << " ";
cout << endl;
p = p->nextarc;
}
}
}
int LocateVertex(AdjGraph G, VertexType v)
{
int i;
for (i = 0; i < G.vexnum; i++)
{
if (strcmp(G.vertex[i].data, v) == 0)
{
return i;
}
}
return -1;
}
void CreateGraph(AdjGraph *G)
{
int i, j, k;
VertexType v1, v2;
ArcNode *p;
cout << "请输入图的定点数和边数:";
cin >> (*G).vexnum >> (*G).arcnum;
cout << "请输入" << G->vexnum << "个顶点的值:" << endl;
for (i = 0; i < G->vexnum; i++)
{
cin >> G->vertex[i].data;
G->vertex[i].firstarc = NULL;
}
cout << "请输入弧尾 弧头:" << endl;
for (k = 0; k < G->arcnum; k++)
{
cin >> v1 >> v2;
i = LocateVertex(*G, v1);
j = LocateVertex(*G, v2);
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->info = NULL;
p->nextarc = G->vertex[i].firstarc;
G->vertex[i].firstarc = p;
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = i;
p->info = NULL;
p->nextarc = G->vertex[j].firstarc;
G->vertex[j].firstarc = p;
}
(*G).kind = UG;
}
void DestroyGraph(AdjGraph *G)
{
int i;
ArcNode *p, *q;
for (i = 0; i < (*G).vexnum; i++)
{
p = G->vertex[i].firstarc;
if (p != NULL)
{
q = p->nextarc;
free(p);
p = q;
}
}
(*G).vexnum = 0;
(*G).arcnum = 0;
}
void main()
{
int k;
AdjGraph G;
CreateGraph(&G);
DisplayGraph(G);
cout << "请输入你要查找距离顶点v0路径为多长的顶点:" << endl;
cin >> k;
BsfLevel(G, 0, k);
DestroyGraph(&G);
system("pause");
}
结果:
请输入图的定点数和边数:8 9
请输入8个顶点的值:
a b c d e f g h
请输入弧尾 弧头:
a b
a d
a c
b e
b f
e h
c h
h g
d g
8个顶点:
a b c d e f g h 9条边:
a->c
a->d
a->b
b->f
b->e
b->a
c->h
c->a
d->g
d->a
e->h
e->b
f->b
g->d
g->h
h->g
h->c
h->e
请输入你要查找距离顶点v0路径为多长的顶点:
2
距离a最短的路径为2的顶点有:h ,g ,f ,e
请按任意键继续. . .