图9——求距离顶点v0的最短长度为k的所有顶点


设计算法求出无向连通区图中距离顶点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
请按任意键继续. . .

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值