Algorithm 非递归n射线树遍历

Algorithm 非递归n射线树遍历,algorithm,recursion,tree,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.chi

给定类定义为:

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);
        }
    }
}
公共静态无效进程(节点){
对于(int i=0;i=node.value){
过程(儿童);
}
}
}
常见的树遍历算法似乎适合这里,因为堆栈pop需要检查条件

真的想不出解决办法

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

5.7 6 1 12 13 5 8 7 10 9 5.5 15 11 14.0

公共类节点{
公共双重价值;
公开儿童名单;
公共节点(双值){
这个值=值;
this.children=new ArrayList();
}
公共void addChild(节点){
添加(节点);
}
公共静态节点createSample(){
节点=新节点(10.0);
节点1=新节点(15.0);
节点2=新节点(6.0);
节点3=新节点(11.0);
节点4=新节点(14.0);
节点5=新节点(5.0);
node.addChild(node1);
node.addChild(node2);
node.addChild(node3);
node.addChild(node4);
节点51=新节点(8.0);
节点52=新节点(7.0);
node5.addChild(node51);
node5.addChild(node52);
node.addChild(node5);
节点11=新节点(9.0);
节点12=新节点(5.5);
node1.addChild(node11);
node1.addChild(node12);
节点21=新节点(5.7);
节点node22=新节点(12.0);
node2.addChild(node21);
node2.addChild(node22);
Node node31=新节点(13.0);
Node node32=新节点(1.0);
node22.addChild(node31);
node22.addChild(node32);
返回节点;
}

}

我不能为您提供一个解决方案,但可以提示您继续使用您的逻辑。想想在内存中执行时使用递归的数据结构。使用该数据结构推送和弹出内容并遍历,直到您的数据结构没有其他内容可遍历为止


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

我不能为您提供一个解决方案,但可以提示您继续使用您的逻辑。想想在内存中执行时使用递归的数据结构。使用该数据结构推送和弹出内容并遍历,直到您的数据结构没有其他内容可遍历为止


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

一种方法是手动实现递归过程,使用递归调用时内存使用的相同机制。也就是说,通过利用内存的堆栈结构进行递归调用。还可以使用与内存使用的堆栈类似的堆栈来模拟非递归树遍历。然后,遍历将由一个循环组成,在这个循环中,您不断将子对象推到堆栈上,然后访问(pop)第一个子对象。当堆栈中没有更多节点时,循环将终止。这与您正在进行的递归遍历相同,也称为后序树遍历。人们甚至可以将这种方法视为深度优先搜索,如果不是用树来处理图形。 然而,有一件事你没有在你的问题中口头提到,那就是需要按照孩子们的价值观的大小来处理他们。为此,您只需要修改将元素放入堆栈的顺序。请记住,由于堆栈是后进先出(LIFO)数据结构,因此需要将值高于父节点的元素放在值较小的元素之前

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

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);
        }
    }
}
类堆栈节点{
公共节点;
公共布尔更大的儿童推;
公共堆栈节点(节点n){
this.node=n;
this.largerchildrenpush=false;
}
}
公共静态作废流程(节点){
Stack st=新堆栈();
st.push(新StackNode(节点));
而(!st.empty()){
StackNode stParent=(StackNode)st.pop();
节点父节点=stParent.Node;
如果(!stParent.largerchildrenpush){
对于(int i=parent.children.size()-1;i>=0;i--){
Node child=parent.children.get(i);
如果(child.value>=parent.value){
st.push(新堆栈节点(子节点));
}
}
圣普什(圣帕伦特);
stParent.largerchildrenpush=true;
对于(int i=parent.children.size()-1;i>=0;i--){
Node child=parent.children.get(i);
if(child.value
一种方法是手动实现递归进程所做的事情,利用在进行递归调用时内存使用的相同机制。也就是说,通过利用内存的堆栈结构进行递归调用。还可以使用与内存使用的堆栈类似的堆栈来模拟非递归树遍历。然后,遍历将由一个循环组成,在这个循环中,您不断将子对象推到堆栈上,然后访问(pop)第一个子对象。循环将在没有数据时终止
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);
        }
    }
}