2013-03-22 98 views
0

有没有办法检索Java的所有叶节点TreeMap检索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)); 
    } 
}); 

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

+1

这没有意义。存储在树叶上的元素取决于“TreeMap”的实现如何平衡树。您是否试图对执行的性能进行基准测试? – 2013-03-22 05:26:17

+0

我知道该怎么做。在TreeMap中,所有叶子都是空的。所以你有他们。最底层的入口不是一片叶子。我想是这样。 – 2013-08-10 14:40:11

回答

2

这对我来说没有多大意义。存储在叶子上的元素取决于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; 

    .... 

似乎没有被任何直接的方式来获得根。但是,如果你可以抓住其中的一个,那么你可以一直遍历到父根,然后以任何你想得到树叶的方式(Entry,其中left == nullright == null)做一个traversal of the tree。顺序遍历将保留排序顺序。

但是,重申一下,我没有看到有什么好的理由说明你想这样做。您还需要在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)); 
    } 

} 
+0

这似乎是实现我自己的树结构的唯一方法。我用这种方法遇到的唯一问题是它不能在另一台机器上工作,对吗?但无论如何,现在这样做。 – 0x56794E 2013-03-22 05:58:46

+0

你能解释为什么你甚至想要这样做,而不仅仅是为了黑客的目的? – 2013-03-22 06:07:04

+0

我正在研究项目的区域划分。树的每个节点代表一个区域,如果获得分区,则会有两个孩子。假设我将区域R0分为R1和R2(在比较器中指定了其他算法,以确定哪个是左边哪个是右边节点)。现在假设R1已经离开了。然后如果R1再次分裂,它会有2个孩子,比如R3和R4。最后,我想按特定顺序获得所有子区域(叶子)。 – 0x56794E 2013-03-22 06:14:25