【问题标题】:Implement the tree in java? not hard coded在java中实现树?没有硬编码
【发布时间】:2021-04-06 00:31:09
【问题描述】:

有一个Tree实现,需要对如何实现逻辑进行修正和思路。

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @param <T>
 */
class TreeNode<T> implements Iterable<TreeNode<T>> {

    private final List<TreeNode<T>> elementsIndex;
    public T data;
    public TreeNode<T> parent;
    public List<TreeNode<T>> children;

    /**
     * @param data
     */
    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
        this.elementsIndex = new LinkedList<TreeNode<T>>();
        this.elementsIndex.add(this);
    }

    /**
     * @param depth
     * @return Indentation
     */
    private static String createIndent(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            sb.append('-');
        }
        return sb.toString();
    }

    /**
     * @return parent
     */
    public boolean isRoot() {
        return parent == null;
    }

    /**
     * @return check the size of child
     */
    public boolean isLeaf() {
        return children.size() == 0;
    }

    /**
     * @param child
     * @return child node
     */
    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        this.registerChildForSearch(childNode);
        return childNode;
    }

    /**
     * @return the depth of the level
     */
    public int getLevel() {
        if (this.isRoot())
            return 0;
        else
            return parent.getLevel() + 1;
    }

    /**
     * @param node
     */
    private void registerChildForSearch(TreeNode<T> node) {
        elementsIndex.add(node);
        if (parent != null)
            parent.registerChildForSearch(node);
    }

    /**
     * @param cmp
     * @return finds the element
     */
    public TreeNode<T> findTreeNode(Comparable<T> cmp) {
        for (TreeNode<T> element : this.elementsIndex) {
            T elData = element.data;
            if (cmp.compareTo(elData) == 0)
                return element;
        }

        return null;
    }

    /**
     * @return the root
     */
    @Override
    public String toString() {
        return data != null ? data.toString() : "[data null]";
    }

    /**
     * @return iterator
     */
    @Override
    public Iterator<TreeNode<T>> iterator() {
        TreeNodeIter<T> iter = new TreeNodeIter<T>(this);
        return iter;
    }

    /**
     * @param treeRoot
     * @param data
     * @return the data else null if not found
     */
    public TreeNode<T> search(TreeNode<T> treeRoot, T data) {

        Comparable<T> searchCriteria = new Comparable<T>() {
            @Override
            public int compareTo(Object treeData) {
                if (treeData == null)
                    return 1;
                boolean nodeOk = treeData.equals(data);
                return nodeOk ? 0 : 1;
            }
        };
        TreeNode<T> found = treeRoot.findTreeNode(searchCriteria);
        return found;
    }

    /**
     * @param treeRoot
     * @return the whole tree
     */
    public StringBuilder display(TreeNode<T> treeRoot) {
        StringBuilder print = new StringBuilder();
        print.append('\n');
        for (TreeNode<T> node : treeRoot) {
            String indent = createIndent(node.getLevel());
            print.append(indent + node.data);
            print.append("\n|");
        }
        if (print.length() > 0)
            print.deleteCharAt(print.length() - 1);
        return print;
    }

}

/**
 * @param <T>
 */
class TreeNodeIter<T> implements Iterator<TreeNode<T>> {

    private final TreeNode<T> treeNode;
    private final Iterator<TreeNode<T>> childrenCurNodeIter;
    private ProcessStages doNext;
    private TreeNode<T> next;
    private Iterator<TreeNode<T>> childrenSubNodeIter;

    /**
     * @param treeNode
     */
    public TreeNodeIter(TreeNode<T> treeNode) {
        this.treeNode = treeNode;
        this.doNext = ProcessStages.ProcessParent;
        this.childrenCurNodeIter = treeNode.children.iterator();
    }

    /**
     * @return true if there is nay element
     */
    @Override
    public boolean hasNext() {

        if (this.doNext == ProcessStages.ProcessParent) {
            this.next = this.treeNode;
            this.doNext = ProcessStages.ProcessChildCurNode;
            return true;
        }

        if (this.doNext == ProcessStages.ProcessChildCurNode) {
            if (childrenCurNodeIter.hasNext()) {
                TreeNode<T> childDirect = childrenCurNodeIter.next();
                childrenSubNodeIter = childDirect.iterator();
                this.doNext = ProcessStages.ProcessChildSubNode;
                return hasNext();
            } else {
                this.doNext = null;
                return false;
            }
        }

        if (this.doNext == ProcessStages.ProcessChildSubNode) {
            if (childrenSubNodeIter.hasNext()) {
                this.next = childrenSubNodeIter.next();
                return true;
            } else {
                this.next = null;
                this.doNext = ProcessStages.ProcessChildCurNode;
                return hasNext();
            }
        }

        return false;
    }

    /**
     * @return the next element
     */
    @Override
    public TreeNode<T> next() {
        return this.next;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    enum ProcessStages {
        ProcessParent,
        ProcessChildCurNode,
        ProcessChildSubNode
    }

}

所以,问题是我有类似这样的数据

Gen
|-Test1
|--Mat
|-Test2
|--123
|---Child's Child
|----Child's Child's Child
|----2406
|-Test3
|--24

但要实现这一点,我必须硬编码这样的代码

public static TreeNode<String> getSet() {
    TreeNode<String> root = new TreeNode<String>("Gen");
    {
        TreeNode<String> node0 = root.addChild("Test1");
        {
            TreeNode<String> node00 = node0.addChild("Mat");
        }
        TreeNode<String> node1 = root.addChild("Test2");
        {
            TreeNode<String> node10 = node1.addChild("123");
            {
                TreeNode<String> node100 = node10.addChild("Child's Child");
                {
                    TreeNode<String> node1000 = node100.addChild("Child's Child's Child");
                    TreeNode<String> node1001 = node100.addChild("2406");
                }
            }
        }
        TreeNode<String> node2 = root.addChild("Test3");
        {
            TreeNode<String> node20 = node2.addChild("24");
        }
        
    }

    return root;
}

}

在顶部,我有一个名为 getPartentChildPart() 的辅助方法,用于获取 MapMap&lt;String,List&lt;String&gt;&gt;

Gen
|-Test1
|--Mat
|-Test2
|--123
|---Child's Child
|----Child's Child's Child
|----2406
|-Test3
|--24

例如,如果我将Gen 作为参数传递给getPartentChildPart(),那么它将返回

Map<Gen,<Test1,Test2,Test3>>

目前我能做到的就是这个

    public void Build(Map<String, List<String>> ROOT)  {
        TreeNode<String> root = null;
        TreeNode<String> node = null;
        for (Map.Entry<String, List<String>> i : ROOT.entrySet()) {
            root = new TreeNode<>(i.getKey());
            for (String j : i.getValue())
            {
                node = root.addChild(j);
                parent = getPartentChildPart(j);
                Build(parent);
            }
            System.out.println("Root"+root.display(root));
        }
    }

    public void Show()  {
        Map<String, List<String>> rt = null;
        rt = getPartentChildPart("Gen");
        Build(rt);
    }

我得到的结果是

Gen
|-Test1
|-Test2
|-Test3

我不明白为什么递归不起作用以及如何实现它...尽管如果我对其进行硬编码,它可以工作,如果我的树在未来增长,那么硬编码将不起作用。

【问题讨论】:

  • 你不能简单地为你的根声明一个静态变量,当你使用 getSet() 时返回它?而不是每次需要时都创建一棵新树。
  • 但如果我这样做,我也将无法获得整棵树。如果我这样做,那么我也会得到这个 ``` Gen |-Test1 |-Test2 |-Test3 ``` 但我需要 ``` Gen |-Test1 |--Mat |-Test2 |--123 |- --孩子的孩子|----孩子的孩子的孩子|----2406 |-Test3 |--24 ``
  • 有没有办法得到一个孩子/孩子的名单?
  • getPartentChildPart() --> 我可以将此方法转换为给出孩子列表。例如,如果我将 Gen 作为 getPartentChildPart() 的参数,那么它将返回 List 确保你看到了整篇文章。
  • 整个帖子我都看过了,我会根据这个添加答案

标签: java list dictionary recursion tree


【解决方案1】:

首先要做的是添加一个返回子列表的方法。从那里递归变得非常简单。

void itChildren(TreeNode<T> node)
{
   // do stuff

   if (!node.getChildren().isEmpty())
   {
      for (int i = 0; i < node.getChildren().size(); i++)
      {
         itChildren(node.getChildren().get(i));
      }
   }

   // do stuff 
}

然后这将遍历整个树。根据您是想在孩子之前(我相信是您的情况)还是之后做事情,您可以将代码放在函数的顶部或底部。

让我知道这是否适合你。

【讨论】:

  • 应该在构建方法中还是在TreeNode实现中使用它?
  • 在构建方法中,或者从任何地方打印你的树。可能最好的方法是创建一个独立于 Build() 的函数,您可以从 Show() 调用该函数。
  • getChildren 应该给我父母的孩子名单!我说的对吗?
【解决方案2】:
final TreeNode<String> struct = "Gen";

public void build(Map<String, List<String>> parentRoot, TreeNode<String> node)  {
        Map<String, List<String>> parent;
        for (Map.Entry<String, List<String>> i : parentRoot.entrySet()) {
            for (Stringj : i.getValue()) {
                TreeNode<String> childNode = node.addChild(new TreeNode<>(j));
                parent = getPartentChildPart(j);
                build(parent, childNode);
               
            }
        }
    }

    
    public void show()  {
        Map<String, List<String>> ROOT = null;
        ROOT = getPartentChildPart("Gen");
        build(ROOT, struct);
        System.out.println(struct.display(struct));
    }

错误是我每次都需要创建一个新节点,并且需要在递归之外获取根。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2018-01-10
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多