树的汇总 用递归与和迭代来实现
创始人
2024-04-07 02:01:07
0

继上次浅谈了树的遍历之后,这次再浅谈一下树的汇总。此处树的汇总是指将树中某节点的数据按指定的汇集到它的父节点中。例 如,可以将树节点中的数值累加到它的父节点中。仍如树的遍历一文,我将使用两种简单的算法,递归与和迭代,来实现这一功能。

1. 树节点

仍然沿用树的遍历一文中的TreeNode/GenericTreeNode,为便于阅读,将GenericTreeNode中的若干关键属性展示如下,

  1. public class GenericTreeNode< T> implements TreeNode {  
  2.  
  3.     private T userObject = null;  
  4.  
  5.     private TreeNode parent = null;  
  6.  
  7.     private List< GenericTreeNode< T>> children = new ArrayList< GenericTreeNode< T>>();  
  8.  
  9.       
  10. }  

2. 递归法

仍然先从最简单的递归法开始,

  1. public static Double recursiveGatherValue(GenericTreeNode< Double> node) {  
  2.     Double sumValue = null;  
  3.     if (node.isLeaf()) {  
  4.         return node.getUserObject();  
  5.     } else {  
  6.         sumValue = node.getUserObject();  
  7.         List< GenericTreeNode< Double>> children = node.getChildren();  
  8.         for (int i = 0, size = children.size(); i <  size; i++) {  
  9.             Double bufGatherValue = recursiveGatherValue(children.get(i));  
  10.             sumValue += bufGatherValue;  
  11.         }  
  12.     }  
  13.  
  14.     node.setUserObject(sumValue);  
  15.     return sumValue;  
  16. }  
  17.  

递归法还是一如既往的简单易懂。与递归遍历树相比,递归汇总树的程序基本上没大的变化,我就不赘述了...

3. 迭代法

与迭代遍历树相比,迭代汇总树的程序有一些明显的变化。当初在思考迭代法时,有个问题一直困绕着我:如何将下级节点的值赋给它的父节点,并且父节点的值要 不断的进行累加。在JavaWorld@TW中提出这个问题之后,很快就得到了清晰的解答(真的很感谢社区里的大大们)。毫无疑问,用迭代法遍历一棵树时 需要使用一个栈,但同时,为了维护节点与汇总值之间的关系,还需要另一个栈进行辅助。具体程序如下所示,

  1. public static void iterativeGatherValue(GenericTreeNode< Double> node) {  
  2.     Stack< NodeValueTuple< Double>> nodeValueStack = new Stack< NodeValueTuple< Double>>();  
  3.     Stack< GenericTreeNode< Double>> nodeStack = new Stack< GenericTreeNode< Double>>();  
  4.  
  5.     nodeStack.push(node);  
  6.     Double sumValue = new Double(0.0D);  
  7.     while (!nodeStack.isEmpty()) {  
  8.         GenericTreeNode< Double> bufNode = nodeStack.pop();  
  9.         if (bufNode == null) {  
  10.             NodeValueTuple< Double> bufNodeValueTuple = nodeValueStack.pop();  
  11.         bufNodeValueTuple.node.setUserObject(sumValue);  
  12.  
  13.         Double bufValue = bufNodeValueTuple.node.getUserObject();  
  14.             sumValue += bufValue;  
  15.         } else if (bufNode.isLeaf()) {  
  16.             sumValue += bufNode.getUserObject();  
  17.         } else {  
  18.             nodeValueStack.add(new NodeValueTuple< Double>(bufNode, sumValue));  
  19.  
  20.             sumValue = new Double(0.0D);  
  21.             nodeStack.push(null);  
  22.             nodeStack.addAll(bufNode.getChildren());  
  23.         }  
  24.     }  
  25. }  

在遍历树的过程中,会将某节点N与它的汇总值一同置入一个栈(nodeValueStack)中,当节点N有子节点时,则将它的子节点及其汇总值也置入栈 中,节点N与它的子节点之间使用一个NULL值进行分隔;如果节点N是叶节点则累加汇总值;如果节点N为NULL,则表示子节点们的汇总已结束,
NodeValueTuple是一个二元组,用于维护节点与它的汇总值之间的关系,代码如下所示,

  1. public class NodeValueTuple< V> {  
  2.  
  3.     public final GenericTreeNode< V> node;  
  4.     public final V value;  
  5.  
  6.     public NodeValueTuple(GenericTreeNode< V> node, V value) {  
  7.         this.node = node;  
  8.         this.value = value;  
  9.     }  
  10. }  

在上述的汇总中,均只累加了叶节点中的数值,而不管分枝节点和根节点本身所拥有的数值。如果要累加这些节点本身的数值,应该如何做呢?大家自己做做看吧, 肯定非常简单 ^_^

4. 小结

树的汇总肯定是一个十分常见的应用,除了汇总数据之外,我们还可以汇集节点中的对象,如汇总挂载在节点上的集合对象中的元素,使得父节点能够拥有所有子节点所拥有的元素。上述方法的效率应该不算低,主要是因为所有的树节点只需要访问一次。

【编辑推荐】

  1. 关于Java垃圾回收问题
  2. Java连接MySQL中文乱码处理
  3. 在Java应用程序中使用Jfreechart配置
  4. 浅谈Java线程的生命周期
  5. 关于Java继承的一些复习

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...