算法设计与分析学习笔记07 | 8月更文挑战

267 阅读2分钟

这是我参与8月更文挑战的第7天,活动详情查看: 8月更文挑战

算法设计与分析题目1

无向连通图找半径最小的生成树

实验目的:

掌握使用图来设计和实现算法

掌握使用邻接表来建立和输出有向图

掌握使用广度优先遍历(DFS)来计算顶点的深度

掌握使用动态规划算法来实现查找半径最小的生成树

内容:

1. 输入有向图的顶点数和边数,及各条边的头和尾

2. 设计函数使用邻接表表示建立和输出无向连通图

3. 设计函数使用广度优先遍历来计算每个顶点作为树根的子树的最大深度

4. 设计函数使用动态规划算法计算顶点和其邻接点表示的子树所构成的子树的最大深度

5. 调用函数,输出无向连通图的最小半径生成树

根据图的邻接表表示无向连通图,通过广度优先遍历和动态规划算法实现其最小半径查找的算法如下,核心代码及注释:

void getDepth(int id)

{

//如果访问过就不再访问

if (v[id]) return;

//标记未访问结点为访问状态

v[id] = true;

head *curPtr = heads[id];

//孤立点的最大深度是0,所以maxD的初始值为0

int maxD = 0;

//遍历邻接表

while (curPtr)

{

//邻居结点的id

int toId = curPtr->toId;

//如果当前邻居点没有处理过,那么需要借助第一遍DFS时生成的countv数组计算以当前结点id以及它的邻居结点toId组成的子树的最大深度

if (!v[toId])

{

//记录

curPtr->maxDepth = countv[toId];

if (countv[toId] > maxD) maxD = countv[toId];

}

//如果当前邻居点处理过了,那需要利用当前邻居结点toId的结果来得到id的状态值

else

{

//遍历toId的所有邻居toIdd。toIdd构成的子树+toId+Id作为一棵新的子树

int maxDD = 1;

head *tempPtr = heads[toId];

while (tempPtr)

{

int toIdd = tempPtr->toId;

if (toIdd != id)

{

if (tempPtr->maxDepth + 1 > maxDD)

maxDD = tempPtr->maxDepth + 1;

}

tempPtr = tempPtr->next;

}

curPtr->maxDepth = maxDD;

if (maxDD > maxD) maxD = maxDD;

}

curPtr = curPtr->next;

}

//更新结果

if (maxD < minDepthVal)

{

minDepthVal = maxD;

num = 1;

res[0] = id;

}

else if (maxD == minDepthVal)

{

res[num++] = id;

}

//DFS

curPtr = heads[id];

while (curPtr)

{

int toId = curPtr->toId;

getDepth(toId);

curPtr = curPtr->next;

}

}

本算法主要是使用邻接表来实现的图的建立并用广度优先遍历和动态规划实现最小半径的查找的,题目要求找出由根到叶子的最短路径,即最小半径,实际上就是要找到深度最小的生成树。

实验结果截图:

图片1.png