开发者

Algorithm to aggregate values from child tree nodes

I have objects in a tree structure, I would like to aggregate status information from children nodes and update parent node with aggregated status. Lets say node A has children B1, B2, and B1 has C1, C2, C3 as children. Each of the nodes have a status attribute开发者_运维知识库.

Now if C1, C2, C3 are all complete then I would like to mark B1 as completed. And if C4, C5,C6,C7 are complete make B2 as complete. When B1 and B2 are both complete mark A as complete.

I can go through these nodes in brute force method and make updates, could someone suggest an efficient algorithm to do it.

A { B1 { C1, C2, C3}, B2 { C4, C5, C6, C7} }


You need post-order traversal - first visit the children of a node, then mark the node itself, recursively.

Something like (pseudocode):

iscomplete(node):
  if node == Null:
     return False
  elsif no children:
     return some "complete" value according to node value
  else:
     for child in node.children:
         if not iscomplete(child):
             return False

  return True


Eli Bendersky has it right, the general answer to this problem is post-order traversal.

For more efficiency, though, you have to use everything you know about the problem. For example, if you can allow some "staleness" then it might be better to cache a complete flag and a timestamp in each node.

Another possibility is that the internal complete status of nodes rarely changes. In this case, it might be much better to propagate up completeness information. Something like that:

class NodeWithCompletenessInfo : public Node {

  private bool internalComplete; // Am I personally done?
  private bool childrenComplete; // Are my children done?

  public bool isComplete() {
    return internalComplete && childrenComplete;
  }

  public void markComplete() {
    internalComplete = true;
    if( isComplete() )
      parent.markChildComplete();
  }

  public void markIncomplete() {
    if( isComplete() )
      parent.markChildIncomplete();
    internalComplete = false;
  }

  private void markChildComplete() {
    for( child in children ) {
      if( !child.isComplete() )
        return;
      childrenComplete = true;
    }
    if( isComplete() )
      parent.markChildComplete()
  }

  private void markChildIncomplete() {
    if( isComplete() )
      parent.markChildIncomplete();
    this.childrenComplete = false;
  }
}


If you know which are leaf nodes then

 A { 
    B1 
        {C1, C2 = false, C3},
    B2 
        {C4, C5=false, C6=false, C7} 
  } // those not marked false are true ;)

not_complete_leaf_nodes_with_different_parents = [ C2 , C5]

mark_not_complete(node):
    node.complete = false
    if parent != null
        mark_not_complete(node.parent)

for each in not_complete_leaf_nodes_with_different_parents:
    mark_not_complete(each.parent)


I can't see that you can evade "brute force".

I would use the visitor design pattern.

http://www.javaworld.com/javaworld/javatips/jw-javatip98.html

http://sourcemaking.com/design_patterns/visitor

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜