非递归n射线树遍历

时间:2016-12-29 08:11:50

标签: algorithm recursion tree

将类定义命名为:

class Node {
    public Double value;
    public List<Node> children;
}

将以下程序翻译成非递归:

public static void process(Node node) { 
    for (int i = 0; i < node.children.size(); i++) {
        Node child = node.children.get(i);
        if (child.value < node.value) {
            process(child);
        }
    }
    System.out.println(node.value);
    for (int i = 0; i < node.children.size(); i++) {
        Node child = node.children.get(i);
        if (child.value >= node.value) {
            process(child);
        }
    }
}

常见的树遍历算法似乎适合这里,因为堆栈弹出需要检查条件。

真的想不出解决方案。

使用示例树时,我得到以下输出,如代码所示:

5.7 6 1.0 12.0 13.0 5 8 7 10.0 9 5.5 15.0 11.0 14.0

public class Node {
public Double value;
public List<Node> children;
public Node(Double value) {
    this.value = value;
    this.children = new ArrayList<Node>();
}
public void addChild(Node node) {
    children.add(node);
}
public static Node createSample() {
    Node node = new Node(10.0);
    Node node1 = new Node(15.0);
    Node node2 = new Node(6.0);
    Node node3 = new Node(11.0);
    Node node4 = new Node(14.0);
    Node node5 = new Node(5.0);
    node.addChild(node1);
    node.addChild(node2);
    node.addChild(node3);
    node.addChild(node4);
    Node node51 = new Node(8.0);
    Node node52 = new Node(7.0);
    node5.addChild(node51);
    node5.addChild(node52);
    node.addChild(node5);
    Node node11 = new Node(9.0);
    Node node12 = new Node(5.5);
    node1.addChild(node11);
    node1.addChild(node12);
    Node node21 = new Node(5.7);
    Node node22 = new Node(12.0);
    node2.addChild(node21);
    node2.addChild(node22);
    Node node31 = new Node(13.0);
    Node node32 = new Node(1.0);
    node22.addChild(node31);
    node22.addChild(node32);
    return node;
}

}

2 个答案:

答案 0 :(得分:1)

我无法为您提供解决方案,但提示您提出您的逻辑。想想在内存中执行时使用递归的数据结构。使用该数据结构来推送和弹出并遍历,直到您的数据结构没有其他任何东西可以遍历。

首先要弄清楚它是哪种树遍历?将你的逻辑分解为小块,并在你的非递归/迭代代码中逐一处理它们。

答案 1 :(得分:1)

一种方法是手动实现递归过程所做的事情,利用内存在进行递归调用时使用的相同机制。即,通过利用存储器的堆栈结构进行递归调用。还可以通过使用类似于存储器使用的堆栈来模拟非递归树遍历。然后,遍历将包含一个循环,您可以继续将孩子推入堆栈,并访问(弹出)第一个孩子。当堆栈中没有更多节点时,循环将终止。这与您正在进行的递归遍历相同,也称为后序树遍历。人们甚至可以将此方法视为深度优先搜索,如果不使用树来处理图形。

然而,你在问题中未能口头提及的一件事是需要按照其价值的数量级处理孩子。为此,您只需要调整将元素放入堆栈的顺序。请记住,由于堆栈是一个LIFO(后进先出)数据结构,因此您需要在值较小的值之前放置值高于父节点的元素。

以下是我上面描述的解决方案的示例,而不是非常有效的实现。您可以在工作中here观察此解决方案,产生您在问题中提供的相同输出。

class StackNode {
    public Node node;
    public boolean largerChildrenPushed;
    public StackNode(Node n) {
        this.node = n;
        this.largerChildrenPushed = false;
    }
}
public static void process(Node node) {
    Stack st = new Stack();
    st.push(new StackNode(node));
    while(!st.empty()) {
        StackNode stParent = (StackNode)st.pop();
        Node parent = stParent.node;
        if(!stParent.largerChildrenPushed) {
            for (int i = parent.children.size() - 1; i >= 0; i--) {
                Node child = parent.children.get(i);
                if (child.value >= parent.value) {
                    st.push(new StackNode(child));
                }
            }
            st.push(stParent);
            stParent.largerChildrenPushed = true;
            for (int i = parent.children.size() - 1; i >= 0; i--) {
                Node child = parent.children.get(i);
                if (child.value < parent.value) {
                    st.push(new StackNode(child));
                }
            }
        }
        else {
            System.out.println(parent.value);
        }
    }
}