如何整理我的 Java 代码,因为它有太多循环 [已关闭]

问题描述 投票:0回答:2

我有一个 Node 类,用于表示树结构。在此类中,我定义了一个打印方法,该方法应产生以下输出:

data
--a (1024)
--b (256)
----ba (100)
------baa (500)
------bac (25)
----bc (150)
----bd (125)
----be (75)
--c (35)
----cb (30)
----ce (50)

这就是我编写打印方法的方式:

public void print(String name) {
        Node node = this.find(name);
        System.out.println(node.name);
        if (node.childrensCount != 0) {
            for (int i = 0; i < node.childrensCount; i++) {
                Node children = node.childrens[i];
                System.out.println("--" + children.name + " (" + children.value + ")");
                if (children.childrensCount != 0) {
                    for (int j = 0; j < children.childrensCount; j++) {
                        Node grandChildren = children.childrens[j];
                        System.out.println("----" + grandChildren.name + " (" + grandChildren.value + ")");
                        if (grandChildren.childrensCount != 0) {
                            for (int k = 0; k < grandChildren.childrensCount; k++) {
                                Node greatGrandChildren = grandChildren.childrens[k];
                                System.out.println("------" + greatGrandChildren.name + " (" + greatGrandChildren.value + ")");
                            }
                        }
                    }
                }
            }
        }
    }

这也是 Node 类的实现,可以更好地帮助你理解场景:

public class Node {

    int value;
    String name;
    Node parent;
    int childrensCount;
    Node[] childrens = new Node[100];

    public Node(int value, String name) {
        this.value = value;
        this.name = name;
        this.childrensCount = 0;
    }

    public Node(String name) {
        this.name = name;
    }
    
    public void addChildren(Node node)
    {
        this.childrens[childrensCount] = node;
        childrensCount++;
    }
    
    public void setParent(Node parent)
    {
        this.parent = parent;
    }
    
    public boolean hasParent(){
        return this.parent != null;
    }
    
    public int sumValue(){
        int sum = 0;
        sum += this.value;
        for (int i = 0; i < childrensCount; i++) {
            sum += childrens[i].value;
        }
        return sum;
    }
}

我认为我的代码很脏,可以改进。我想定义一个递归方法,但我仍然不明白递归是如何工作的。有人可以帮我吗?

java recursion tree
2个回答
2
投票

您可以使用递归来完成。我没有尝试重建所有复杂的数据,而是使用我自己的节点类创建了一个简单的示例。

class MyNode {
    String name;
    List<MyNode> nodeList;
    
    public MyNode(String name) {
        this.name = name;
    }
    
    public MyNode setNodeList(List<MyNode> list) {
        nodeList = list;
        return this;
    }
    @Override
    public String toString() {
        return name;
    }
    public List<MyNode> getNodeList() {
        return nodeList;
    }
}

    
    
MyNode m = new MyNode("a");
List<MyNode> list1 =
        List.of(new MyNode("aaa"), new MyNode("aab"),
                new MyNode("aac"), new MyNode("aad"));
List<MyNode> list2 = List.of(new MyNode("aba"),
        new MyNode("abb"), new MyNode("abc"));
List<MyNode> list3 = List.of(new MyNode("aca"),
        new MyNode("acb"), new MyNode("acc"));
List<MyNode> list4 = List.of(new MyNode("ada"),
        new MyNode("adb"), new MyNode("adc"));

List<MyNode> mainlist = List.of(new MyNode("aa").setNodeList(list1),
        new MyNode("ab").setNodeList(list2), new MyNode("ac").setNodeList(list3), new MyNode("ad").setNodeList(list4));
        

m.setNodeList(mainlist);
print(m,1);

打印

--a
----aa
------aaa
------aab
------aac
------aad
----ab
------aba
------abb
------abc
----ac
------aca
------acb
------acc
----ad
------ada
------adb
------adc
  • 这是通过让 print 方法调用自身并调整缩进级别来实现的。
  • 打印当前节点和级别。
  • 如果该节点的列表非空,则为列表中的每个节点调用 print 方法,并重复该过程,更新级别。
  • 每次返回时,该方法都会从中断处开始,同时继续调用自身并返回。
  • 这是遍历分层数据集的常见过程,并且将处理不确定数量的级别。
public static void print(MyNode node, int level) {
    System.out.println("-".repeat(level*2) + node);
    if (node.getNodeList() != null) {
       for (MyNode n : node.getNodeList()) {
                print(n, level+1);
        }
    }
}

我建议您阅读递归过程。 在某些情况下,您还可以在遍历层次结构时返回值。


1
投票

要定义递归方法,您首先需要确定您的基本情况递归情况。在这种情况下,基本情况是当用于打印的节点是

null
时,而递归情况是当仍有子节点要打印时。

由于我猜测您的计划可能是学校练习,因此我将避免讨论如何更好地实施您的

Node
课程。当然,使用集合框架中的
List
比使用固定的
100
元素数组会是更好的选择,但我猜你的老师想让事情变得简单,或者你可能还没有涵盖集合框架.

无论如何,我在这里附加了一个解决方案来展示您的递归打印如何工作。请记住,我已将打印实现分为两个方法,只是为了使客户端调用更容易。事实上,您的代码的客户端不应该知道也不应该担心使用您的代码的内部实现细节。


//Test class
public class Test {
    public static void main(String[] args) {
        Node root = new Node(1, "test1", new Node[]{
                new Node(2, "test2", new Node[]{
                        new Node(5, "test6", new Node[]{})
                }),
                new Node(3, "test3", new Node[]{
                        new Node(6, "test6", new Node[]{}),
                        new Node(7, "test7", new Node[]{
                                new Node(8, "test8", new Node[]{})
                        })
                }),
                new Node(4, "test4", new Node[]{})
        });

        root.print();
    }
}

class Node {

    int value;
    String name;
    Node parent;
    int childrenCount;
    Node[] children = new Node[100];

    public Node(int value, String name) {
        this.value = value;
        this.name = name;
        this.childrenCount = 0;
    }

    //Added second constructor only to ease the test
    public Node(int value, String name, Node[] children) {
        this.value = value;
        this.name = name;
        this.children = children;
        this.childrenCount = getNumChildren(children);
    }

    public Node(String name) {
        this.name = name;
    }

    //Fixed possible exception when added more than 100 elements
    public boolean addChildren(Node node) {
        if (childrenCount == this.children.length) {
            return false;
        }
        this.children[childrenCount++] = node;
        return true;
    }

    public void setParent(Node parent) {
        this.parent = parent;
    }

    public boolean hasParent() {
        return this.parent != null;
    }

    public int sumValue() {
        int sum = 0;
        sum += this.value;
        for (int i = 0; i < childrenCount; i++) {
            sum += children[i].value;
        }
        return sum;
    }

    // small utility method to compute the effective number of children
    // when an array is passed to the new constructor
    public static int getNumChildren(Node[] children) {
        int num = 0;
        while (num < children.length && children[num] != null) {
            num++;
        }
        return num;
    }

    //print method invoked by the client of the class
    public void print() {
        printRec(this, 0);
    }

    //recursive print
    private void printRec(Node n, int numCall) {
        //identifying the base case
        if (n == null) {
            return;
        }

        //Printing as many dahses as the depth of the current child node
        for (int i = 1; i <= numCall; i++) {
            System.out.print("--");
        }

        //printing the node info
        System.out.println(n.name + " (" + n.value + ")");

        //recursively invoking the print method for each child
        for (int i = 0; i < n.childrenCount; i++) {
            printRec(n.children[i], numCall + 1);
        }
    }
}

在这里,我只是添加了一些旁注:

  • children 已经是 child 的复数形式。您不需要将数组称为子数组。

  • 如果添加的元素超过 100 个,则您对

    add
    方法的实现可能会抛出
    ArraIndexOutOfBoundsException
    。通常,当操作可能失败时,该方法应返回一个布尔值来告诉客户端操作是否成功。

© www.soinside.com 2019 - 2024. All rights reserved.