用java实现树?非硬编码

mznpcxlj  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(369)

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

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;
}

}
在上面,我调用了helper方法 getPartentChildPart() 方法,该方法用于获取Map<parent,list>,即 Map<String,List<String>> ```
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> ROOT) {
TreeNode root = null;
TreeNode node = null;
for (Map.Entry<String, List> 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

我不明白为什么递归不起作用,我怎么能实现这个。。。虽然如果我硬编码这个它可以工作,如果我的树在未来增长,那么硬编码将不工作。
thigvfpy

thigvfpy1#

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));
    }

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

inn6fuwd

inn6fuwd2#

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

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 
}

这将遍历整个树。根据您是想在子对象之前(我相信这是您的情况)还是之后执行操作,您可以将代码放在函数的顶部或底部。
让我知道这是否适合你。

相关问题