Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 递归-如果节点的字符串为“0”,则删除节点;“莱昂纳多”;_Java_Algorithm_Recursion_Graph Algorithm_Breadth First Search - Fatal编程技术网

Java 递归-如果节点的字符串为“0”,则删除节点;“莱昂纳多”;

Java 递归-如果节点的字符串为“0”,则删除节点;“莱昂纳多”;,java,algorithm,recursion,graph-algorithm,breadth-first-search,Java,Algorithm,Recursion,Graph Algorithm,Breadth First Search,我有一个节点树 class Node { String mName; List<Node> children = new ArrayList<>(); Node(String name) { mName = name; } } 结果应该是: Jessy / | \ Rafael David J

我有一个节点树

class Node {
    String mName;
    List<Node> children = new ArrayList<>();
    Node(String name) {
        mName = name;
    }
}
结果应该是:

                        Jessy
                   /      |       \
 Rafael  David           John         Denis  Phillipe
                          |             
                        Keren         
(关于莱昂纳多、丹尼斯、菲利普和莱昂纳多的子树结果的解释:杰西的第三个儿子是莱昂纳多,因此莱昂纳多被移除,他的儿子(丹尼斯和莱昂纳多)成为杰西的儿子。但是,另一个莱昂纳多被移除,菲利普代替他而来。)

孩子们的顺序无关紧要(也就是说,拉斐尔和大卫可以跟在菲利普后面)

假设“Leonardo”在根中时无法获得初始树

我已经试过了,但不幸的是它不起作用

for (int i = 0; i < root.children.size(); ++i) {
        removeLeonardo(root, root.children.get(i));
}

public void removeLeonardo(Node curr, Node child) {
    if (child == null || child.children.isEmpty() == true) {
        return;
    }

    if (child.mName.equals("Leonardo") == true) {
        // add all Leonardo's children to current father
        for (int i = 0; i < child.children.size(); ++i) {
            curr.children.add(child.children.get(i));
            // apply the func for the current father with each of Leonardo's children
            removeLeonardo(curr, child.children.get(i));
        }
        // remove "Leonardo" from the current father
        curr.children.remove(child);
    }

    else { // no "Leonardo" found, so apply the func for each child and this child's children
        for (int i = 0; i < child.children.size(); ++i) {
            removeLeonardo(child, child.children.get(i));
        }
    }
}
for(int i=0;i

但是Java不能通过引用工作。你能帮我解决这个问题吗?

我相信这应该行得通

如果您担心效率,那么从ArrayList内部删除并插入ArrayList并不是最好的选择。LinkedList会更好,但这样你就不想通过子对象的索引来访问它们了。您可能会改用ListIterator,并使用add和remove方法

public static void main(String[] args)
{
    Node root = new Node("Jessy");
    root.children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("John"), new Node("Leonardo")}));      
    root.children.get(0).children.addAll(Arrays.asList(new Node[]{new Node("Rafael"), new Node("David")}));
    root.children.get(1).children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("Keren")}));
    root.children.get(2).children.addAll(Arrays.asList(new Node[]{new Node("Denis"), new Node("Leonardo")}));
    root.children.get(2).children.get(1).children.add(new Node("Phillipe"));

    print(root, "");                
    pruneByName(root, "Leonardo");
    print(root, "");
}

static void pruneByName(Node node, String name)
{       
    assert !node.mName.equals(name);

    for(int i=0; i<node.children.size(); )
    {
        Node child = node.children.get(i);
        if(child.mName.equals(name))
        {
            node.children.remove(i);
            node.children.addAll(i, child.children);
        }
        else
        {
            pruneByName(child, name);
            i += 1;
        }
    }
}

static void print(Node node, String ind)
{
    System.out.println(ind + node.mName);
    for(Node child : node.children)
    {
        print(child, ind + "  ");
    }
}

我相信这应该行得通

如果您担心效率,那么从ArrayList内部删除并插入ArrayList并不是最好的选择。LinkedList会更好,但这样你就不想通过子对象的索引来访问它们了。您可能会改用ListIterator,并使用add和remove方法

public static void main(String[] args)
{
    Node root = new Node("Jessy");
    root.children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("John"), new Node("Leonardo")}));      
    root.children.get(0).children.addAll(Arrays.asList(new Node[]{new Node("Rafael"), new Node("David")}));
    root.children.get(1).children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("Keren")}));
    root.children.get(2).children.addAll(Arrays.asList(new Node[]{new Node("Denis"), new Node("Leonardo")}));
    root.children.get(2).children.get(1).children.add(new Node("Phillipe"));

    print(root, "");                
    pruneByName(root, "Leonardo");
    print(root, "");
}

static void pruneByName(Node node, String name)
{       
    assert !node.mName.equals(name);

    for(int i=0; i<node.children.size(); )
    {
        Node child = node.children.get(i);
        if(child.mName.equals(name))
        {
            node.children.remove(i);
            node.children.addAll(i, child.children);
        }
        else
        {
            pruneByName(child, name);
            i += 1;
        }
    }
}

static void print(Node node, String ind)
{
    System.out.println(ind + node.mName);
    for(Node child : node.children)
    {
        print(child, ind + "  ");
    }
}

在初始循环中跳过子John。这是怎么做的

杰西的孩子莱昂纳多、约翰等在数组列表的索引0、1等处。
for
循环从索引0开始,处理第一个莱昂纳多和那个莱昂纳多 被移除。在除掉莱昂纳多的过程中,指数1的约翰, 将移动到索引0。for循环然后移动到索引1,跳过John和 不带走约翰的孩子,莱昂纳多

下面是使用
ListIterator
解决问题的代码。用这个 代码您可以使用任何类型的列表,包括
LinkedList
,以及
ArrayList

public static void removeLeonardo2(Node node) {
    if (node == null || node.children.isEmpty()) {
        return;
    }

    for(ListIterator<Node> it = node.children.listIterator(); it.hasNext();) {
        Node n;
        n = it.next();
        if(n.mName.equals("Leonardo")) {
            removeLeonardo2(n);
            it.remove();
            for(Node childNode: n.children) {
                it.add(childNode);;
            }
        }else {
            removeLeonardo2(n);
        }
    }
}
public static void removeLeonardo2(节点){
if(node==null | | node.children.isEmpty()){
回来
}
for(ListIterator it=node.children.ListIterator();it.hasNext();){
节点n;
n=it.next();
如果(n.mName.等于(“莱昂纳多”)){
去除氧自由基(n);
it.remove();
用于(节点子节点:n个子节点){
添加(childNode);;
}
}否则{
去除氧自由基(n);
}
}
}

在初始循环中跳过子John。这是怎么做的

杰西的孩子莱昂纳多、约翰等在数组列表的索引0、1等处。
for
循环从索引0开始,处理第一个莱昂纳多和那个莱昂纳多 被移除。在除掉莱昂纳多的过程中,指数1的约翰, 将移动到索引0。for循环然后移动到索引1,跳过John和 不带走约翰的孩子,莱昂纳多

下面是使用
ListIterator
解决问题的代码。用这个 代码您可以使用任何类型的列表,包括
LinkedList
,以及
ArrayList

public static void removeLeonardo2(Node node) {
    if (node == null || node.children.isEmpty()) {
        return;
    }

    for(ListIterator<Node> it = node.children.listIterator(); it.hasNext();) {
        Node n;
        n = it.next();
        if(n.mName.equals("Leonardo")) {
            removeLeonardo2(n);
            it.remove();
            for(Node childNode: n.children) {
                it.add(childNode);;
            }
        }else {
            removeLeonardo2(n);
        }
    }
}
public static void removeLeonardo2(节点){
if(node==null | | node.children.isEmpty()){
回来
}
for(ListIterator it=node.children.ListIterator();it.hasNext();){
节点n;
n=it.next();
如果(n.mName.等于(“莱昂纳多”)){
去除氧自由基(n);
it.remove();
用于(节点子节点:n个子节点){
添加(childNode);;
}
}否则{
去除氧自由基(n);
}
}
}

谢谢@YvetteColomb:)谢谢@YvetteColomb:)