gpt4 book ai didi

java - 访问 SortedSet 中特定元素的最有效方法是什么?

转载 作者:行者123 更新时间:2023-12-04 14:00:00 26 4
gpt4 key购买 nike

我想使用一个排序的集合,但我可以通过索引访问其中的元素,即我想要一些同时具有 Set 和 List 特征的东西。 Java.util.TreeSet 非常接近我的需要,但不允许通过索引访问。

我可以想到几个选项:

  1. 每次需要特定元素时,我都可以遍历 TreeSet。
  2. 我可以维护一个 TreeSet 并在需要访问特定元素时从中生成一个列表。
  3. 同上,只缓存List直到Set改变。
  4. 我可以有一个列表,并在需要添加元素时自己对其进行排序。
  5. 等等

各种选项之间存在各种权衡。我希望有人能给我一些好的建议。要回答“您为什么要这样做?”等潜在问题,请阅读 Apriori算法。

最佳答案

https://github.com/geniot/indexed-tree-map

我遇到了同样的问题。于是我把java.util.TreeMap的源码拿来写了IndexedTreeMap。它实现了我自己的 IndexedNavigableMap:

public interface IndexedNavigableMap<K, V> extends NavigableMap<K, V> {
K exactKey(int index);
Entry<K, V> exactEntry(int index);
int keyIndex(K k);
}

该实现基于在红黑树中更改时更新节点权重。权重是给定节点下的子节点数加上一个 - 自身。例如,当一棵树向左旋转时:

    private void rotateLeft(Entry<K, V> p) {
if (p != null) {
Entry<K, V> r = p.right;

int delta = getWeight(r.left) - getWeight(p.right);
p.right = r.left;
p.updateWeight(delta);

if (r.left != null) {
r.left.parent = p;
}

r.parent = p.parent;


if (p.parent == null) {
root = r;
} else if (p.parent.left == p) {
delta = getWeight(r) - getWeight(p.parent.left);
p.parent.left = r;
p.parent.updateWeight(delta);
} else {
delta = getWeight(r) - getWeight(p.parent.right);
p.parent.right = r;
p.parent.updateWeight(delta);
}

delta = getWeight(p) - getWeight(r.left);
r.left = p;
r.updateWeight(delta);

p.parent = r;
}
}

updateWeight 只是将权重更新到根:

   void updateWeight(int delta) {
weight += delta;
Entry<K, V> p = parent;
while (p != null) {
p.weight += delta;
p = p.parent;
}
}

当我们需要通过索引查找元素时,这里是使用权重的实现:

public K exactKey(int index) {
if (index < 0 || index > size() - 1) {
throw new ArrayIndexOutOfBoundsException();
}
return getExactKey(root, index);
}

private K getExactKey(Entry<K, V> e, int index) {
if (e.left == null && index == 0) {
return e.key;
}
if (e.left == null && e.right == null) {
return e.key;
}
if (e.left != null && e.left.weight > index) {
return getExactKey(e.left, index);
}
if (e.left != null && e.left.weight == index) {
return e.key;
}
return getExactKey(e.right, index - (e.left == null ? 0 : e.left.weight) - 1);
}

查找键的索引也非常方便:

    public int keyIndex(K key) {
if (key == null) {
throw new NullPointerException();
}
Entry<K, V> e = getEntry(key);
if (e == null) {
throw new NullPointerException();
}
if (e == root) {
return getWeight(e) - getWeight(e.right) - 1;//index to return
}
int index = 0;
int cmp;
index += getWeight(e.left);

Entry<K, V> p = e.parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
while (p != null) {
cmp = cpr.compare(key, p.key);
if (cmp > 0) {
index += getWeight(p.left) + 1;
}
p = p.parent;
}
} else {
Comparable<? super K> k = (Comparable<? super K>) key;
while (p != null) {
if (k.compareTo(p.key) > 0) {
index += getWeight(p.left) + 1;
}
p = p.parent;
}
}
return index;
}

您可以在 https://github.com/geniot/indexed-tree-map 找到这项工作的结果

关于java - 访问 SortedSet 中特定元素的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5334020/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com