![](/img/trans.png)
[英]How to insert a node to a list with given data and maintain the list to be sorted in java
[英]Maintain a sorted list with performance
我的问题摘要:我需要一个可以快速迭代和排序的列表(通过排序方法或添加/删除对象)。
我正在编写一个游戏,其中有很多“碰撞区”,每一帧都会检查。 为了优化,我有一个关于它们的排序的想法取决于它们的X位置。 问题不是所有碰撞区域都是静态的,因为它们中的一些可以移动。
我已设法处理所有更改,但维护使用Collections.sort()
排序的ArrayList
(或ConcurrentLinkedQueue
)太慢。
所以我有了一个新想法:我可以使用一个树,每当一个区域的X被更改,而不是再次排序所有元素,我可以删除然后从树重新添加它。 但是,我认为在TreeList中添加和删除运算符也很昂贵。 而且,迭代Tree不如ConcurrentLinkedQueue
, LinkedList
或ArrayList
。
请告诉我是否有任何内置数据结构满足我的需要。 如果没有这样的数据结构,我打算扩展ArrayList
类,重写add
方法以确保顺序(通过使用重载add(index, item)
。如果你认为这是最好的方法,请给我最好的方法找到索引。我已经使用了BinarySearch,但我认为有一个错误:
@Override
public boolean add(T e) {
// Find the position
int left = 0;
int right = this.size() - 1;
int pos = right / 2;
if (e.compareTo(this.get(0)) <= 0) {
pos = 0;
} else if (e.compareTo(this.get(this.size() - 1)) >= 0) {
pos = this.size();
} else {
// Need: e[pos - 1] <= e[pos] <= e[pos + 1]
boolean firstCondition = false;
boolean secondCondition = false;
do {
firstCondition = this.get(pos - 1).compareTo(this.get(pos)) <= 0;
secondCondition = this.get(pos).compareTo(this.get(pos + 1)) >= 0;
if (!firstCondition) {
right = pos - 1;
pos = (left + right) / 2;
} else if (!secondCondition) {
left = pos + 1;
pos = (left + right) / 2;
}
} while (!(firstCondition && secondCondition));
}
this.add(pos, e);
return true;
}
我会用树集。 如果需要允许重复,可以使用自定义比较器。 迭代树集比数组略慢,添加和删除要快得多。
看来你正在进行插入排序,即O(n)。 树集上的插入是O(ln n)
恕我直言通过使用TreeMap<MyKey, List<MyType>>
这样存储重复项的最佳方法
Map<MyKey, List<MyType>> map = new TreeMap<>();
// to add
MyType type = ...
MyKey key = ...
List<MyType> myTypes = map.get(key);
if (myTypes == null)
map.put(key, myTypes = new ArrayList<>());
myTypes.add(type);
// to remove
MyType type = ...
MyKey key = ...
List<MyType> myTypes = map.get(key);
if (myTypes != null) {
myTypes.remove(myType);
if (myTypes.isEmpty())
map.remove(key);
}
在这种情况下,添加和去除是O(ln N);
您可以通过将所有对象定义为不同来允许“重复”是TreeSet
Set<MyType> set = new TreeSet<>(new Comparator<MyType>() {
public int compare(MyType o1, MyType o2) {
int cmp = /* compare the normal way */
if (cmp == 0) {
// or use System.identityHashCode()
cmp = Integer.compare(o1.hashCode(), o2.hashCode());
return cmp == 0 ? 1 : cmp; // returning 0 is a bad idea.
}
}
}
正如你所看到的,这种方法很难看,除非你有办法让每个对象都独一无二。
听起来你想要一个TreeSet 。
如果您打算在已排序的数组或ArrayList上使用二进制搜索/插入,那么您将获得与二叉树相同的大O复杂度。
因此,我建议您执行测试提供的树实现(即TreeSet
),而不仅仅是猜测。 因为它们不是普通的树实现,所以如果迭代对它们来说也很快就不会感到惊讶。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.