遍历
遍历树
不像一个数组或者是一组被设计成按顺序处理的数字,树不呈现元素的线性配置;相反,处理可以发生在给定节点或节点的任何子节点上。
由于这种类型的算法在遍历树时必须选择下一个要处理的节点,因此算法必须记住它没有访问的节点,以便稍后探索它们。为了达到这个目的,算法采用了一种堆栈,其中最近存储的节点具有优先级;或者一个队列,其中存储在数组中的第一个项具有最高优先级。这些技术通常使用递归,它允许少量的指令或代码行。具体使用的技术取决于预期的目的,无论是解决问题搜索,分而治之,或图论问题,以及其他许多。
排队就像一排人一样,第一个来的人首先得到服务。这种数据存储技术也称为FIFO,即先进先出。另一方面,把堆叠想象成一堆盘子,上面的最后一个是第一个被使用的。这也被称为后进先出。
深度优先搜索
深度优先搜索DFS是一种策略,它沿着一个分支一直走下去,直到到达一个叶子,处理所述的分支,然后移动到另一个分支。这种类型的算法通常使用堆栈来跟踪访问的节点,因为最后看到的节点是下一个要访问的节点,其余的节点被存储起来以供以后访问。
伪代码[3]
1 2 3 4 5 6 7 8 9 10初始化一个空堆栈用于存储节点s,对于每个顶点u,定义u.visited为false。将根节点(第一个被访问的节点)推入S,当S不为空时:弹出S中的第一个元素u。如果u.visited = false,则:u.visited = true对于u的每个未被访问的邻居w:将w推入S,当所有节点都被访问时结束进程。
没有recrustion的Python实现
1 2 3 4 5 6 7 8defdepht_first_search(图):参观了,堆栈=集(),[根]而堆栈:顶点=堆栈.流行()如果顶点不在参观了:参观了.添加(顶点)堆栈.扩展(图[顶点]-参观了)返回参观了
DFS还可以使用递归实现,这大大减少了代码行数。
使用递归的Python实现
1 2 3 4 5 6 7defdepth_first_search_recursive(图,开始,参观了=没有一个):如果参观了是没有一个:参观了=集()参观了.添加(开始)为下一个在图[开始]-参观了:depth_first_search_recursive(图,下一个,参观了)返回参观了
修改算法以跟踪边而不是顶点是很常见的,因为每条边都描述了每一端的节点。这在处理完每个节点后试图重构遍历树时非常有用。对于森林或一组树,该算法可以扩展为包含一个外部循环,迭代所有树,以便处理每个节点。
实现DFS有三种不同的策略:预购,按次序的,后序.
预购DFS的工作原理是访问当前节点,然后依次向左移动,直到到达一个叶节点,在到达的过程中访问每个节点。一旦节点的左边不再有子节点,就会访问右边的子节点。这是最标准的DFS算法。
它不是在树中遍历每个节点,而是按次序的算法找到树中最左边的节点,访问该节点,然后访问该节点的父节点。然后它转到右边的子节点,并找到树中最左边的下一个节点进行访问。
一个后序策略的工作原理是访问树中最左边的叶节点,然后向上访问同一分支中的父节点,然后向下访问同一分支中第二个最左边的叶节点,以此类推,直到父节点成为分支中要访问的最后一个节点。如果目标位于树的末端,这种类型的算法会优先处理叶结点,而不是根结点。
深度优先搜索算法被广泛应用于图论:当发现最短路径比如,检测一个循环,找到连接的组件,给树排序,或者在迷宫中找到出口或目标。
广度优先搜索
广度优先搜索在树遍历技术中,BFS与DFS是对等的。它是一种搜索算法,使用队列作为其数据数组向下遍历树,其中元素以FIFO(先进先出)机制访问。这种策略也被称为level-order遍历,即在进入下一层之前访问一层上的所有节点。
BFS的伪代码与DFS的伪代码完全相同,除了a队列用来代替堆栈来存储未访问的节点。这将改变被访问节点的顺序,因为按时间顺序,第一个被存储的节点具有最高优先级,接下来将被访问。换句话说,BFS在访问一个节点的邻居之前会访问该节点的所有邻居。
伪代码[3]
1 2 3 4 5 6 7 8 9 10初始化一个空队列用于存储节点s,对于每个顶点u,定义u.visited为false。将根节点(第一个被访问的节点)推入S,当S不为空时:弹出S: u中的最后一个元素。如果u.visited = false,则:u.visited = true对于u的每个未被访问的邻居w:将w推入S,当所有节点都被访问时结束进程。
Python实现
1 2 3 4 5 6 7 8defbreadth_first_search(图):参观了,队列=集(),[根]而队列:顶点=队列.流行(0)如果顶点不在参观了:参观了.添加(顶点)队列.扩展(图[顶点]-参观了)返回参观了
可选遍历技术
已经开发了其他不使用BFS或DFS遍历树的算法。这些算法包括蒙特卡罗树搜索,利用随机抽样穿过树;还有很多其他的图搜索算法它们试图利用额外的信息快速有效地找到给定的目的地。其中包括爬坡算法,波束搜索算法,分支定界算法,以及一个*算法,所有这些都使用启发式或其他图形见解,以确定遍历的最佳下一步。
树遍历问题的另一个例子是无限的树,其中实际上有无限个节点。这些类型的树代表着巨大的问题复杂的空间例如下棋的电脑或最近开发的围棋电脑。这些问题给简单的DFS和BFS实现带来了困难,因为对于使用DFS的实现,算法可能永远不会访问分支的末尾,或者对于使用BFS的实现,算法可能永远不会访问每个分支。
获得更多树遍历应用程序计算机科学,请参阅柯尼希无穷大引理,旅行推销员问题,切尼的算法,或福特·富尔克森的算法.
参考文献
- 石头汤,J。减少。重用。“回收利用”。3r是如何帮你洗碗的.从检索http://thestonesoup.com/blog/2011/01/reduce-reuse-recycle-how-the-3rs-can-help-you-with-the-washing-up/
- Pixabay,。行,人.从检索https://pixabay.com/static/uploads/photo/2014/08/31/00/58/people-431943_960_720.jpg
- 堆,D。深度优先搜索(DFS).检索,2002年12月16日,从http://www.cs.toronto.edu/~heap/270F02/node36.html
- 维基,M。Depth-First-Search.gif.检索2016年7月15日,从https://commons.wikimedia.org/wiki/File:Depth-First-Search.gif
- 维基,M。文件:Depth-First-Search.gif.从检索https://upload.wikimedia.org/wikipedia/commons/5/5d/Breadth-First-Search-Algorithm.gif)