Tree 遍历无序二叉树

Tree 遍历无序二叉树,tree,parallel-processing,Tree,Parallel Processing,我需要以并行方式访问树。 怎么可能呢?如果没有递归,我无法在树中想到任何东西。不确定您是否仍在寻找关于此问题的答案,但我认为其他人可能会受益 您仍然可以使用递归,但您需要锁定树的分支,并允许其他线程“跳过”这些分支,因为它们已经在或已经被处理 例如,假设您正在处理一棵树,进行广度优先遍历,因此在递归方法的每次运行中,您都要遍历当前节点的子节点。每个线程必须遍历当前节点的子节点,并尝试锁定每个子节点,如果已经锁定,则跳过该子节点 我不确定您使用的是什么树实现,所以您应该将下面示例代码中的“Node

我需要以并行方式访问树。
怎么可能呢?如果没有递归,我无法在树中想到任何东西。

不确定您是否仍在寻找关于此问题的答案,但我认为其他人可能会受益

您仍然可以使用递归,但您需要锁定树的分支,并允许其他线程“跳过”这些分支,因为它们已经在或已经被处理

例如,假设您正在处理一棵树,进行广度优先遍历,因此在递归方法的每次运行中,您都要遍历当前节点的子节点。每个线程必须遍历当前节点的子节点,并尝试锁定每个子节点,如果已经锁定,则跳过该子节点

我不确定您使用的是什么树实现,所以您应该将下面示例代码中的“Node”对象视为伪代码,但其余的都是正确的Java

在下面的示例中,选择了一个预定的深度来应用锁定-这确保了线程不会简单地锁定在树的根上,而是序列化对整个树的访问

选择正确的深度取决于特定树的形状。例如,如果它是一个二叉树,那么您的树在深度3处可能有多达8个分支,这对于几个线程来说是最好的,但是如果您运行20个线程,则需要选择一个较低深度的序列化点,以确保所有线程都能够处理某个分支

您还可以使用其他一些方法来决定何时锁定,例如,如果节点可以有效地报告它有多少叶节点,您可以设置阈值,重要的是所有线程使用相同的代码来决定是否锁定

Object master_LOCK = new Object();
HashMap locks = new HashMap();
int DEPTH = 5;

public boolean lockNode(Object nodeID) {
    synchronized(master_LOCK) {
        Object node_LOCK = (Object)locks.get(nodeID);
        if (node_LOCK == null) {
            //we can lock this node
            locks.put(nodeID,new Object());
            return true;
        } else {
            //node already locked
            return false;
        }
    }
}

public void traverseBreadhFirst(Node node) {    
    locks.clear();
    traverseBreadthFirst(node,0);
}

public void traverseBreadthFirst(Node node, int currentDepth) {
    currentDepth++;

    //Process the current node here


    //Iterate through children, locking to force serialised access only at a predetermined depth
    List children = node.getChildren();

    for (int i = 0; i < children.size(); i++) {

        Node child = (Node)children.get(i);

        //If we are a certain depth in the tree we start serialising access from that point on
        //This ensures that there are enough branches at this point to roughly evenly distribute them 
        //to all available threads.

        if (currentDepth < DEPTH ) {
            //All threads are to go to depth N
            traverseBreadthFirst(node,currentDepth);

        } else if (currentDepth == DEPTH ) {
            //At depth N we lock all branches we intend to process
            if (lockNode(child.getID())) {
                //We have locked this child node so we should process it
                traverseBreadthFirst(node,currentDepth);
            } else {
                //This child has been locked for processing already so we skip it
            }

        } else {
            //We are deeper than depth N so we can traverse our locked branch without locking further
            traverseBreadthFirst(node,currentDepth);

        }
    }

}