7.8总结与提高
【主要知识点】
- (1)基本概念:
图中顶点间的关系可以任意的,因此图是最复杂的非线性结构,它的表达力强。
图具有有向图、无向图、连通图、强连通图、完全图、赋权图等多种类型。 - (2)图的存储结构:
图的存储方式一般有两类,用边的集合方式有邻接矩阵,链接方式有邻接表、 十字链表、邻接多重表。
邻接矩阵和邻接表是两种常用的存储结构,适用于有向图(网)和无向图(网) 表示与处理。 - (3)图的基本操作:
由于图中结点间可以是多对多的关系,为实现图的遍历必须设置访问标志数 组,以防止走回路或未访问到。 图的遍历规律有两种:深度优先遍历 DFS 和广度优先遍历 BFS。可用用邻 接矩阵和邻接表实现深度优先遍历和广度优先遍历算法。
深度优先遍历算法是以递归技术为支持,而广度优先遍历算法是以队列技术为支持。 - (4)图的应用: 图的遍历算法是图应用的重要基础。求解生成树、最小生成树、连通分量, 拓扑排序、关键路径、单源最短路径及所有顶点之间的最短路径的重要算法应用。
【典型题例】
例 1 求距离顶点 v0 的最短路径长度为 k 的所有顶点 已知无向图 g,设计算法求距离顶点 v0 的最短路径长度为 K 的所有顶点,要求尽可能节省时间
【问题分析】由于题目要求找出最短路径长度为 k 的所有顶点,故从顶点 v0 开 始进行广度优先搜索,将一步可达的、两步可达的…直至 k 步可达的所有顶点记 录下来,同时用一个队列记录每个结点的层号,输出第 K+1 层的所有结点即为所求。
【算法描述】
void bfsKLevel(Graph g, int v0, int K)
{
InitQueue( Q1); /* Q1 是存放已访问顶点的队列 */
InitQueue( Q2); /* Q2 是存放已访问顶点层号的队列 */
for ( i=0; i < g .vexnum; i++)
visited[i]=FALSE; /* 初始化访问标志数组 */
visited[v0]=TRUE;
Level=1;
EnterQueue( Q1, v0);
EnterQueue( Q2, Level);
while (! IsEmpty( Q1) && Level<K+1)
{
v=DeleteQueue( Q1); /* 取出已访问的顶点号 */
Level=DeleteQueue( Q2); /* 取出已访问顶点的层号 */
w=FirstAdjVertex(g, v); /* 找第一个邻接点 */
while ( w!=-1 )
{
if (! visited[w] )
{
if (Level==K)
printf(“%d”, w); /* 输出符合条件的结点 */
visited[w]=TRUE;
EnterQueue( Q1, w);
EnterQueue( Q2, Level+1);
}
w=NextAdjVertex(g, v, w); /* 找下一个邻接点 */
}
}
}
例 2 设计算法在图 g 中找出一条包含所有顶点的简单路径
【问题分析】从任一顶点开始进行深度优先搜索,同时记录当前路径结点序列和 当前路径结点数目。当递归进层时结点数目加 1,当递归退层时结点数目减 1, 当结点数目等于结点总数时,输出当前路径结点序列,成功返回。
【算法描述】
int visited[MAX_VERTEX_NUM];
int path[MAX_VERTEX_NUM]; /* 记录路径上的顶点序列 */
int n; /* 记录路径上的顶点数 */
int DepthFirstSearch(Graph g , int v0) /* 用递归的深度优先搜索法在图 g 中寻找一条包含所有顶点的简单路径。 从当前结点 v0 成功找到时返回 1,否则返回 0 */
{
visited[v0]=TRUE; /* 设置访问标志 */
n=n+1; /* 递归进层时,路径上顶点数加 1 */
path[n]=v0; /* 保存路径上的顶点 */
if (n==g .vexnum )
{
Display(path); /* 找到一条包含所有顶点的简单路径 */
return 1; /* 成功返回 */
}
w= FirstAdjVertex (g, v0); /* 找第一个邻接点 */
while (w!=-1)
{
if (! visited[w] && DepthFirstSearch (g, w)==1)
return 1; /* 从邻接点 w 往下搜索,且成功返回 */
w=NextAdjVertex (g, v0, w); /* 找下一个邻接点 */
}
visited[v0]=FALSE; /* 递归退层时,取消访问标志,以便重新遍历该顶点 */
n=n-1; /* 递归退层时,路径上顶点数减 1 */
return 0; /* 从当前结点v0出发,无法找到解路径,失败返回 */
}
void Hamilton(Graph g)
{
for ( i=0; i < g .vexnum; i++)
visited[i]=FALSE; /* 初始化访问标志数组 */
n=0; /* 初始化路径上的顶点数 */
for ( i=0; i < g .vexnum; i++)
if (DepthFirstSearch (g, i)==1)
return;/* 一旦找到一条简单路径则返回 */
}
例 3 求图的中心顶点 假设有一个公司在某个地区有 n 个产品销售点,现根据业务需要打算在其中某个销售点上建立一个中心仓库,负责向其它销售点提供产品。由于运输线路不同,运输费用也不同。假定每天需要向每个销售点运输一次产品,那么应将中心 仓库建在哪个销售点上,才能使运输费用达到最低。
【问题分析】这是一个求图的中心顶点的问题:即在一个带权图 G 中,求出这 样一个顶点 v,使得 v 到其余顶点的最短路径长度之和最小。首先用弗罗伊德算 法求出各个顶点之间的最短路径长度,然后再求出每个顶点到其余各顶点的最短 路径长度之和,从中选取一个最短路径长度之和最小的顶点。
【算法描述】
#define MAXLEN 3E38 /*定义最大浮点数*/
#define MAX 20 /*定义最大顶点数目*/
int CenterVex (AdjMatrix G)
{ /*在带权图 G 中求一个中心顶点,返回该顶点编号*/
int i, j, k;
float min, len;
float A[MAX][ MAX]; /* A[i][j]存放 i 和 j 之间的最短路径长度*/
for (i=0; i<G.vexnum; i++)
{ /* 初始化 A[i][j] */
for (j=0; j<G.vexnum; j++)
A[i][j]=G.arcs[i][j].adj;
A[i][i]=0; /* i 到 i 的路径长度为 0 */ }
for (k=0; i<G.vexnum; k++) /*求出每一对顶点之间的最短路径长度*/
for (i=0; i<G.vexnum; i++)
for (j=0; j<G.vexnum; j++)
if (A[i][k]+A[k][j]<A[i][j])
A[i][j]=A[i][k]+A[k][j];
min=MAXLEN;
k=0;
for (i=0; i<G.vexnum; i++)
{ /*选择最短路径长度之和最小的顶点 vK*/
len=0;
for(j=0; j<G.vexnum; j++) /*求 vi 到其余顶点最短路径长度之和*/
len=len+A[i][j];
if(len<min)
{
k=i;
min=len;
}
}
return(k);
}
本文深入探讨了图的理论及其在信息技术中的应用,包括图的存储结构如邻接矩阵和邻接表,以及图的遍历算法如深度优先遍历(DFS)和广度优先遍历(BFS)。通过实例展示了如何利用BFS寻找特定长度的最短路径,以及如何使用DFS找到包含所有顶点的简单路径。此外,还讨论了在实际问题中,如何利用图的算法解决最小运输成本问题,即寻找图的中心顶点。这些算法在图论和计算机科学中具有广泛的应用价值。
3222

被折叠的 条评论
为什么被折叠?



