【问题标题】:Retrieve all the leaf nodes of java TreeMap检索java TreeMap的所有叶子节点
【发布时间】:2013-03-11 21:13:06
【问题描述】:

有没有办法检索 Java TreeMap 的所有叶节点?

我有一个这样的TreeMap

TreeMap<String, FooBar> myTree = new TreeMap<String, FooBar>(new Comparator<String>() {
  public int compare(String o1, String o2)
  {
    int b1 = Integer.parseInt(o1, 2);
    int b2 = Integer.parseInt(o2, 2);
    return (b1 > b2 ? 1 : (b1 == b2 ? 0 : -2));
  }
});

如何获取这棵树的所有叶子节点?

【问题讨论】:

  • 这没有意义。存储在叶子上的元素取决于TreeMap 的实现如何平衡树。您是否尝试对实施的性能进行基准测试?
  • 我知道该怎么做。在 TreeMap 中,所有叶子都为空。所以你有它们。最底部的条目不是叶子。我想是的。

标签: java map binary-tree treemap


【解决方案1】:

这对我来说没有多大意义。存储在叶子上的元素取决于 TreeMap 的实现如何平衡树。

但是,假设您出于某种原因需要这样做。要真正做到这一点,你需要做一些小技巧:编写一个封装在java.util 中的类,它可以访问TreeMap 的包私有方法。

经过一番挖掘,发现JDK中默认的树实现是红黑树,它的Entry实现如下:

static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left = null;
    Entry<K,V> right = null;
    Entry<K,V> parent;
    boolean color = BLACK;

    ....

似乎没有任何直接的方法可以找到根源。但是,如果你能抓住其中一个Entryies,你可以一直遍历父节点直到根,然后以任何你想得到叶子的方式执行traversal of the treeEntry where @987654328 @ 和 right == null)。中序遍历将保留已排序的顺序。

但是,重申一下,我看不出你有什么好的理由要这样做。您还需要在java.util 包中执行此操作,以便能够调查那些Entryies。但这是代码,为了好玩。 (如果不覆盖 JVM 上的安全限制,您将无法执行此操作。)

package java.util;

import java.util.TreeMap.Entry;

public class TreeMapHax {

    static <K,V> List<Entry<K, V>> getLeafEntries(TreeMap<K, V> map) {      
        Entry<K, V> root = map.getFirstEntry();
        while( root.parent != null ) root = root.parent;

        List<Entry<K,V>> l = new LinkedList<Entry<K,V>>();
        visitInOrderLeaves(root, l);
        return l;
    }

    static <K,V> void visitInOrderLeaves(Entry<K, V> node, List<Entry<K, V>> accum) {       
        if( node.left != null ) visitInOrderLeaves(node.left, accum);       
        if( node.left == null && node.right == null ) accum.add(node);      
        if( node.right != null ) visitInOrderLeaves(node.right, accum);
    }

    public static void main(String[] args) {
        TreeMap<String, Integer> map = new TreeMap<String, Integer>();

        for( int i = 0; i < 10; i++ )
            map.put(Integer.toString(i), i);

        System.out.println(getLeafEntries(map));
    }

}

【讨论】:

  • 这似乎是除了实现我自己的树结构之外的唯一方法。我对这种方法的唯一问题是它不能在另一台机器上工作,不是吗?但无论如何,现在就可以了。
  • 你能解释一下为什么你甚至想要这样做而不是仅仅为了黑客目的吗?
  • 我正在处理一个项目的区域分区部分。树的每个节点代表一个区域,如果得到分区,将有两个子节点。假设我将区域 R0 分为 R1 和 R2(比较器中指定了其他算法来确定哪个是左侧节点,哪个是右侧节点)。假设现在留下 R1。然后,如果 R1 再次被划分,它将有 2 个孩子,比如 R3 和 R4。最后,我想按特定顺序获取所有子区域(叶子)。
  • 您知道树会旋转以平衡自身,对吧?即使您可以按照您所说的解释树,父子关系也可以切换。您指定的比较器仅确定顺序遍历关系,不能强制执行父子关系。
  • 好点。对于哪种数据结构最适合执行这种父子关系,您有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-16
  • 1970-01-01
  • 1970-01-01
  • 2017-06-22
  • 2017-07-29
  • 2020-05-16
相关资源
最近更新 更多