Java中的可分级高效排序结构

时间:2013-05-30 21:11:55

标签: java collections sorted

我查看了(可能是几十个)StackOverflow问题,我认为我找不到我想要的内容。

我想要一个具有以下属性的Java结构:

  1. 排序
  2. 可迭代
  3. 支持泛型
  4. O(logn)(或更好)插入和删除
  5. O(logn)(或更好)元素访问
  6. 允许重复输入
  7. 为什么呢?我正在实现k-最近距离算法。对于数据集合中的每个点,我需要找到距离第k个最近的点的距离。该算法通过迭代每对点,计算它们之间的距离,然后将该距离添加到每个点的最近距离的排序结构(如果距离比该列表中的其他元素更近)来工作。以下是一些演示代码:

    ArrayList<SortedThing<Double>> nearestDistances = new ArrayList<SortedThing<Double>>(numPoints);
    for (int i = 0; i < numPoints; i++) {
        nearestDistances.add(new SortedThing<Double>(k));
    }
    
    for (int point = 0; point < numPoints; point++) {
        for (int otherPoint = point+1; otherPoint < numPoints; otherPoint++) {
            double distance = computeDistance(point, otherPoint);
    
            if (nearestDistances.get(point).size < k)
                nearestDistances.get(point).add(distance);
            else if (nearestDistances.get(point).last() > distance) {
                nearestDistances.get(point).removeLast();
                nearestDistances.get(point).add(distance);
            }
    
            if (nearestDistances.get(otherPoint).size < k)
                nearestDistances.get(otherPoint).add(distance);
            else if (nearestDistances.get(otherPoint).last() > distance) {
                nearestDistances.get(otherPoint).removeLast();
                nearestDistances.get(otherPoint).add(distance);
            }
        }
    }
    

    在您建议任何以下内置Java类之前,这就是我不想使用它们的原因:

    1. PriorityQueue - 无法访问其中的最后一个元素
    2. TreeSet - 不允许重复距离
    3. ArrayList - 是的,我可以使用ArrayList,将所有n-1个距离插入其中,在O(nlogn)时间内对其进行排序,然后删除第k个元素。但是,这将需要O(n ^ 2)空间而不是O(nk)空间。
    4. ArrayList - 或者,我可以维护一个已排序的ArrayList,删除最后一个元素并在正确的位置插入新元素,但插入每个插入需要O(k)时间,而O(logk)要查找插入的位置。
    5. 有谁知道这样的结构?我最近一直在考虑这个问题,并且让我感到困惑的是Java没有提供任何这样的结构。

2 个答案:

答案 0 :(得分:1)

如果您正在进行最近邻搜索,那么您可能想要使用k-d tree; here's a Java implementation(查看.jar​​文件中的\ bak目录中的源代码)

否则,我建议使用TreeMap,其中值是密钥重复的数量(1表示没有重复,2表示重复,等等)

Map<Key, Integer> map = new TreeMap<>();

if(map.containsKey(key)) {
    map.put(key, map.get(key) + 1);
} else {
    map.put(key, 1);
}

答案 1 :(得分:1)

TreeBag检查Apache Commons Collections

TreeBag使用TreeMap来保留条目。