基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径

问题

假设图G采用邻接表存储,设计一个算法,求不带权无向连通图G中从顶点u->v的最短路径(路径上经过的顶点数最少。采用广度优先遍历来实现。

基本思路

我们首先来看一下BFS的过程:
基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径_第1张图片
图片摘自慕课网李春葆老师讲的数据结构。从图中我们可以看到BFS的过程就是给定一个起点u,从起点u到某一个顶点(假设v)的最短路径构成分层。
下面我先给出一个代码,然后再给出一个例题并进行分析。

代码

typedef struct ANode {
	int adjvex;				//该边的终点编号
	struct ANode *nextarc;	//指向下一条边的指针
	int name[10];			//该边的权值等信息
}ArcNode;

typedef struct Vnode {
	char data;				//顶点信息
	ArcNode *firstarc;		//指向第一条边
}VNode;

typedef struct {
	VNode adjlist[MAXV];	//邻接表
	int n, e;				//途中顶点数n和边数e
}ALGraph;

typedef struct {
	int data;		//顶点编号
	int parent;		//前一个顶点的位置
}QUERE;

void ShortPath(ALGraph *G, int u, int v) {
	//输出从顶点u到顶点v的最短逆路径
	ArcNode *p; int w, i;
	QUERE qu[MAXV];							//定义非循环队列
	int front = -1, rear = -1;				//队列的头、尾指针
	int visited[MAXV];
	for (i = 0; i < G->n; i++)
		visited[i] = 0;
	rear++;
	qu[rear].data = u;
	qu[rear].parent = -1;
	visited[u] = 1;
	
	while (front != rear) {					//队不空循环
		front++;
		w = qu[front].data;
		if (w == v) {
			i = front;
			while (qu[i].parent != -1) {
				cout << qu[i].data << " ";
				i = qu[i].parent;
			}
			cout << qu[i].data << " " << endl;
			break;
		}

		p = G->adjlist[w].firstarc;				//找w的第一个邻接点
		while (p != NULL) {
			if (visited[p->adjvex] == 0) {
				visited[p->adjvex] == 1;
				rear++;							//将w未访问过的邻接点进队
				qu[rear].data = p->adjvex;
				qu[rear].parent = front;
			}
			p = p->nextarc;						//找w的下一个邻接点
		}
	}
}

例题

基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径_第2张图片
这里假设起点u=1,终点v=4。要求,求出起点u->v的最短路径。

核心思想

在到达某一点之后遍历这个点所能到达的所有点,并记录能够到达这个点的上一个点。

例题分析

我们可以先画出这个图的邻接表结构:
基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径_第3张图片
根据代码我们可以列出三个表来表示运行的过程,各个变量的数值变化:
基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径_第4张图片
最左边的这个表表示,图的每个节点是否被访问,visited[i]=1,表示 i 这个节点已经被访问过。从上到下表示了程序运行过程中各个节点被访问的先后顺序。中间的这个表,表示front 和 rear 这两个变量的值随着程序运行而变化的结果。最右边的表表示了,data和parent的这两个变量值的变化。
最终程序输出4-2-1。正好是正确答案的倒序。

你可能感兴趣的:(算法与数据结构)