课程笔记 17:数据结构(清华) 图-遍历
来源:互联网 发布:图像识别算法 知乎 编辑:程序博客网 时间:2024/05/29 14:39
我们之前研究的树结构是一种半线性结构,为了利用之前研究相对成熟的线性结构如向量、列表,我们会采用遍历手法来将树转化为线性结构来研究。同样的,在研究图这一非线性结构时,我们同样可以通过遍历手法将其转化为非线性结构——树来研究。
在进行树的遍历算法时,关键的地方是选定当前顶点的下一个对象。通常,我们有两种选定方法。其一是对于越早被访问到的顶点,其邻居就会越优先被选用。这种方法被称为广度优先搜索。其二是直接将当前顶点的最近邻居作为当前顶点,直到某一个顶点没有邻接顶点,再返回上一顶点,继续访问其邻居顶点 。这种方法被称为深度优先搜索。
现在,我们先探讨广度优先搜索的实现。假定我们选定某一个顶点作为初始顶点,那么该顶点的所有邻接顶点都将在第一轮遍历中被访问到,我们可以把初始顶点视为树根,而把这些邻接顶点视为树的第一层子节点。继而,在第二轮遍历中,我们将依次访问第一层每个节点的所有邻接顶点,并把它们视为树的第二层子节点。以此类推,我们将得到一颗完整的树。
仔细观察上述遍历过程,不难发现我们对遍历树的访问次序就是对树进行层次遍历的次序。这就提示我们可以采用在树的层次遍历中所采用的策略一样,利用队列来实现图的广度优先搜索。根据一思路,我们可以写出如下的代码 :
template<typename Tv, typename Te>
voidGraph::BFS(int u, int& clock)
{
queue<int>Q;
Q.enqueue(u);
while ( !Q.empty())
{
u = Q.dequeue();
for ( int s =firstNbr(u); s > -1; s = nextNbr(u, s) )
{
if ( V[s].status== UNDISCOVRED )
{
Q.enqueue(s);
E[u][s].status =TREE;
V[s].parent =V[u];
V[s].dTime = ++clock;
V[s],status =DISCOVERED;
}
else
E[u][s] = CROSS;
}
V[u].status =VISITED;
}
}
为了保证整个图的每一个顶点和边能无一遗漏的被访问到,我们需要对所有的顶点进行一遍扫描来确认每一个顶点的状态都是VISITED。
template<typename Tv, typename Te>
void Graph::bfs()
{
int clock = 0;
for ( int u = 0; u< n; u ++ )
if ( V[u].status!= VISITED ) BFS(u, clock);
}
深度优先算法比广度优先算法更容易理解,但是在实现方面却更为复杂。因为深度优先搜索需要标记的边的状态较多,讨论也较为复杂。一般来说,我们把在遍历形成的支撑树中由祖先节点指向后代节点的非树边记为FORWARD,而由后代节点指向祖先节点的非树边记为BACKWARD,另外,无直系血缘关系的节点间的非树边记为CROSS。现在我们就可以着手进行深度优先搜索的设计了。
template<typename Tv, typename Te>
void Graph::DFS(int u, int& clock)
{
V[u].status =DISCOVERED;
V[u].dTime = ++clock;
for ( int s =firstNbr(u); s > -1; s = nextNbr(u, s) )
{
switch (V[s].status )
{
case UNDISCOVERED:
E[u][s].status =TREE;
V[s].parent = u;
DFS(s, clock);
break;
case DISCOVERED:
E[u][s].status =BACKWARD;
break;
default :
E[u][s].status = (V[s].dTime > V[u].dTime ) ? FORWARD: CROSS;
break;
}
}
V[u].status =VISITED;
V[u].fTime = ++clock;
}
和BFS一样,我们同样需要对所有顶点进行一遍扫描来确保每一个顶点的状态都是VISITED。
template<typename Tv, typename Te>
void Graph::dfs()
{
int clock = 0;
for ( int u = 0; u< n; u ++ )
if ( V[u].status!= VISITED ) BFS(u, clock);
}
- 课程笔记 17:数据结构(清华) 图-遍历
- 课程笔记 14:数据结构(清华) 二叉树-遍历
- 课程笔记 15:数据结构(清华) 图
- 课程笔记 16:数据结构(清华) 图-邻接矩阵
- 课程笔记 01:数据结构(清华) 绪论
- 课程笔记 02:数据结构(清华) 向量
- 课程笔记 03 :数据结构(清华) 向量
- 课程笔记 07:数据结构(清华) 列表
- 课程笔记 10:数据结构(清华) 栈
- 课程笔记 04 :数据结构(清华) 向量-查找算法
- 课程笔记 05:数据结构(清华) 向量-排序
- 课程笔记 06:数据结构(清华) 列表-节点
- 课程笔记 08:数据结构(清华) 列表-读写接口
- 课程笔记 09:数据结构(清华) 列表-排序器
- 课程笔记 11:数据结构(清华) 栈与队列
- 课程笔记 12:数据结构(清华) 二叉树-节点
- 课程笔记 13:数据结构(清华) 二叉树
- 数据结构学习笔记 --- 图(遍历)
- C++中的覆盖、重载与隐藏
- 解决android中加载大图时出现的内存溢出问题
- 01背包问题
- DOM
- Linux 学习笔记
- 课程笔记 17:数据结构(清华) 图-遍历
- uva 10344 23 out of 5(递归+全排列)
- Windows中制作傻瓜式安装 Yosemite黑苹果教程。看完你就懂了会了
- 学习笔记:AlexNet&Imagenet学习笔记
- iOS总结控件三(UItextField)
- 代码对齐UVa1593
- JavaScript的语法
- 在 UITabBarController 和 UINavigationController tableView被navigati
- MySql避免重复插入记录方法(ignore,Replace,ON DUPLICATE KEY UPDATE)