【问题标题】:Appropriate datastructure to use for children of a tree用于树的孩子的适当数据结构
【发布时间】:2018-09-10 19:11:39
【问题描述】:

所以我想实现一个树的严格定义——一个没有任何循环的图。递归地,它是一个具有 n 个子树/子节点的节点。因此,每个节点都需要某种数据结构来将它与它的 n 个子树关联起来。

  • 数组、列表、序列、有序集合:子级并没有真正的排序。有一种特殊类型的树称为“有序树”,它确实将某种排序与节点的子节点相关联,但这在这里似乎不合适。

    例如:

    Tree(3, Tree(4), Tree(5) ) == Tree(3, Tree(5), Tree(4) )

  • 集合:集合没有顺序,但也不包含重复项。从功能上讲,如果 Tree(3) == Tree(3) 是有意义的,但我们需要重复信息,因为一个节点可以有多个 Tree(3) 作为子树。

    例如:

    Tree(3, Tree(4) ) != Tree(3, Tree(4), Tree(4) )

  • Bag:一个无序集合,允许添加项目,但不允许删除任何项目。这似乎与可以移除树上的孩子这一事实不一致。

还有其他更合适的无序数据结构吗?我确定这是以前的问题,常见的解决方案是什么?

谢谢!

【问题讨论】:

  • 我不知道你到目前为止尝试了什么 - 一个无序的将通过硬编码节点之间的链接和它的孩子来完成。 - 就像一棵二叉树。如果你想要一个有序的树,那么你可以尝试 BST 或 Max/Min heap。你可以看看这个链接:stackoverflow.com/questions/49598967/…
  • 硬编码似乎只有在你有像 BinTree 这样有固定数量的孩子而不是可变数量的孩子的情况下才真正起作用。我想一种方法可能只是表示整个事物,例如有顶点和节点的图。但这摆脱了保证无循环规则。我觉得这里可能有一个优雅的解决方案,比如哈希图,但这需要所有东西都定义一些哈希。
  • 一个非常有用的数据结构是left-child, right-sibling binary tree。这使您可以非常简单地表示任何类型的树,每个节点具有任意数量的子节点。
  • 我相信这将使相等比较变得困难,因为无论顺序如何,都需要检查兄弟姐妹的链接列表的内容。我觉得哈希表可能最适合以后进行相等比较。

标签: data-structures tree unordered


【解决方案1】:

如果儿童订单无关紧要并且允许重复,我认为List 就足够了。

由于没有保证孩子将在列表中排序或以正确的顺序插入,并且由于允许重复而不能使用Set,我们可以定义如何比较两棵树以便@987654323 @ 和 Tree(3, ArrayList(Tree(5), Tree(4)) 可以比较为相等。

一种方法是 - 在比较它们是否相等时,我们可以根据孩子的值对它们进行排序并递归地比较它们。

class Tree {
    private Integer value;
    private List<Tree> children;

    // getter for value
    // getter for children

    public Tree(Integer value) {
        this.value = value;
        children = new ArrayList<>();
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (!(other instanceof Tree)) {
            return false;
        }
        Tree otherTree = (Tree) other;

        return equalUtil(this, otherTree);
    }

    private boolean equalUtil(Tree lhs, Tree rhs) {
        if(lhs == null && rhs == null) {
            return true;
        }

        if(lhs == null || rhs == null) {
            return false;
        }


        if(lhs.children.size() != rhs.children.size()) {
            return false;
        }

        // copying the children into another list to not altering
        // the tree's data ordering
        lhsChildren = lhs.children;
        Collections.sort(lhsChildren, new TreeComparator());

        rhsChildren = rhs.children;
        Collections.sort(rhsChildren, new TreeComparator());

        for(int i = 0; i < lhsChildren.size(); i++) {
            if(!equalUtil(lhsChildren[i], rhsChildren[i])) {
                return false;
            }
        }

        return true;

    }

    static class TreeComparator implements Comparator<Tree> {
        @Override
        public int compare(Tree lhs, Tree rhs) {
            return lhs.getValue().compareTo(rhs.getValue());
        }
    }
}

【讨论】:

  • 嗨,这似乎是蛮力比较,如 Tree(3, ArrayList(Tree(4), Tree(5)) != Tree(3, ArrayList(Tree(5), Tree( 4)) 当它们真的应该是。我想你可以保持两个数组列表的顺序,但不能保证 Tree 封装的值会有顺序。
  • 啊,好吧。现在我明白了你的问题。让我更新我的答案
猜你喜欢
  • 2015-03-02
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多