Traditional Ways of Tree Traversal

This page contains examples of some “standard” traversal algorithms (ones that can be found in most textbooks). All examples perform pre-order tree traversal on a general rooted tree. “Algorithms, Data Structures and Problem Solving with C++” by Mark Allen Weiss (Addison-Wesley, 1995) gives the following definition of the general rooted tree:

  • One node is distinguished as a root.
  • Every node c, except the root, is connected by an edge from exactly one other node pp is the parent and c is one of p‘s children.
  • There is a unique path from the root to each node. The number of edges that must follow is the path length (sometimes it is called “depth”).

Binary trees and their variations (AVL, red-black and so forth) are not considered here.

Each example performs full traversal of a DOM tree and prints name and value of each node. An XML parser, for example Apache’s Xerces, is needed in order to run the code.

Example 1. Traversal using recursion

Recursive traversal is the best known and most frequently used. Recursive algorithm uses method call stack in order to keep the state of the traversal for every level of a tree. There is a common misconception that recursive algorithms are slow because of the call stack copying overhead. I have not found it to be the case in Java, at least it is not the case for methods with small number of local variables.



import org.w3c.dom.*;

public class RecursiveTraversal implements ITraversal {

  /**
* Performs full tree traversal using recursion.
*/
public void traverse( Node parentNode ) {
// traverse all nodes that belong to the parent
for(Node node=parentNode.getFirstChild(); node!=null; node=node.getNextSibling()
) {
// print node information
System.out.println( node.getNodeName()+"="+node.getNodeValue());
// traverse children
traverse(node);
}
}
}

Example 2. Traversal using stack

A stack object is used to store tree level’s state thus eliminating the need for recursion.

Note that in reality you don’t want to use java.util.Stack because its methods are synchronized. It also inherits from Vector and its methods are synchronized as well. So some sort of custom stack class (for example, based on java.util.ArrayList) should be used instead.



import org.w3c.dom.*;
import java.util.*; public class StackTraversal implements ITraversal { /**
* Performs full tree traversal using stack.
*/
public void traverse( Node rootNode ) { Stack stack = new Stack();
// ignore root -- root acts as a container
Node node=rootNode.getFirstChild(); while (node!=null) {
// print node information
System.out.println( node.getNodeName()+"="+node.getNodeValue()); if ( node.hasChildNodes()) {
// store next sibling in the stack. We return to it after all children are
processed.
if (node.getNextSibling()!=null)
stack.push( node.getNextSibling() );
node = node.getFirstChild();
}
else {
node = node.getNextSibling();
if (node==null && !stack.isEmpty())
// return to the parent's level.
// note that some levels can be skipped if the parent's node was the last one.
node=(Node) stack.pop();
}
}
}
}

Example 3. Traversal using child-parent link

It is possible to avoid using stack for treelike structures that provide support for child-parent link. Link from child to parent can be used to return back to the parent level once the child level is processed. This link effectively simulates stack, so there is no need for a separate stack object. Most of the tree types (including DOM) do support child-parent link. This is probably the most elegant way of traversing a tree — no recursion or stack is involved.



import org.w3c.dom.*;

public class LinkTraversal implements ITraversal {

  /**
* Performs full tree traversal using child-parent link.
*/
public void traverse( Node rootNode ) { // ignore root -- root acts as a container
Node node=rootNode.getFirstChild(); while (node!=null) {
// print node information
System.out.println( node.getNodeName()+"="+node.getNodeValue()); if ( node.hasChildNodes()) {
node = node.getFirstChild();
}
else { // leaf
// find the parent level
while (node.getNextSibling()==null && node != rootNode)
// use child-parent link to get to the parent level
node=node.getParentNode(); node = node.getNextSibling();
}
}
}
}

Tree 使用方式的更多相关文章

  1. EasyUI Tree递归方式获取JSON

    最近需要用到EASYUI中的TREE功能,以前我是直接拼接成<UL><LI>发现这样拼完之后在更改树后对树的刷新不是很理想,现改用JSON格式,首先分析TREE中JOSN格式如 ...

  2. 数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction

    Tree Construction Problem's Link ------------------------------------------------------------------- ...

  3. Device Tree(三):代码分析【转】

    转自:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html Device Tree(三):代码分析 作者:linuxer 发布于:201 ...

  4. Device Tree(三):代码分析

    一.前言 Device Tree总共有三篇,分别是: 1.为何要引入Device Tree,这个机制是用来解决什么问题的?(请参考引入Device Tree的原因) 2.Device Tree的基础概 ...

  5. 【转】Device Tree(三):代码分析

    原文网址:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html 一.前言 Device Tree总共有三篇,分别是: 1.为何要引入De ...

  6. XGBoost 与 Boosted Tree

    http://www.52cs.org/?p=429 作者:陈天奇,毕业于上海交通大学ACM班,现就读于华盛顿大学,从事大规模机器学习研究. 注解:truth4sex  编者按:本文是对开源xgboo ...

  7. 转 Velocity中加载vm文件的三种方式

    Velocity中加载vm文件的三种方式   velocitypropertiespath Velocity中加载vm文件的三种方式:    方式一:加载classpath目录下的vm文件 Prope ...

  8. orocos_kdl学习(二):KDL Tree与机器人运动学

    KDL(Kinematics and Dynamics Library)中定义了一个树来代表机器人的运动学和动力学参数,ROS中的kdl_parser提供了工具能将机器人描述文件URDF转换为KDL ...

  9. Boosted Tree

    原文:http://www.52cs.org/?p=429 作者:陈天奇,毕业于上海交通大学ACM班,现就读于华盛顿大学,从事大规模机器学习研究. 注解:truth4sex  编者按:本文是对开源xg ...

随机推荐

  1. Jquery简略API使用

    都是个人随手笔记,既然开通了博客园就分享给大家.谨做为参考,具体大家自己测试以及使用 ★ $() ★ JQ的一个万能获取对象的函数(获取跟CSS获取元素是一样的)$(function(){}); 替代 ...

  2. python学习第九天 -- 列表生产式

    说说python特有的列表生成式.python的列表的生成式主要用法是什么? 用法就是可以使用简洁的代码生成出list集合. 直接用代码举了例子: 利用列表生成式生成列表[1x2,3x4,5x6,7x ...

  3. XML DOM 遍历Xml文档

    1.xml文档内容: <?xml version="1.0" encoding="utf-8" ?> <bookstore> <b ...

  4. Android MVP模式 简单易懂的介绍方式

    主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200

  5. (摘)C#comboBox绑定数据

    C#中comboBox用代码绑定数据库中在某一列.用处:跟radioButton联系在一起,可以根据radioButton在选择而在comboBox显示出不同的值. private void radi ...

  6. 第8章 Android数据存储与IO——File存储

    openFileOutput/openFileInput 这是android自带的两种解决方案.

  7. jquery.mmenu

    http://mmenu.frebsite.nl/ 左右滑动效果 http://blog.sina.com.cn/s/blog_6a0a183f0100zsfk.html js的左右滑动触屏事件,主要 ...

  8. resultMap之collection聚集

    <select id="getCarsWithCollection" resultMap="superCarResult"> select c1.c ...

  9. Mysql unix_timestamp() FROM_UNIXTIME和DATE_FORMAT(date,format)

    mysql 中:UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date) 若无参数调用,则返回一个 Unix timestamp ('1970-01-01 00:00:00' GM ...

  10. Linux企业级项目实践之网络爬虫(12)——处理HTTP应答头

    Web服务器的HTTP应答一般由以下几项构成:一个状态行,一个或多个应答头,一个空行,内容文档.设置HTTP应答头往往和设置状态行中的状态代码结合起来.例如,有好几个表示"文档位置已经改变& ...