【发布时间】:2016-01-23 19:28:49
【问题描述】:
我知道由于各种概念原因,Java 没有排序列表,但考虑到我需要一个类似于优先级队列但也允许我随机访问(可索引)的集合的情况,换句话说,我需要一个遵循特定顺序的列表。我希望不使用Collections.sort()
优选的操作约束:
检索 - O(1)(基于索引的随机访问)
搜索 - O(log n)
插入 - O(log n)
删除 - O(log n)
集合上的迭代器应该为我提供排序顺序中的所有元素(基于在数据结构实例化期间提供的预定义Comparator)
我更喜欢使用 Java 的内置库来实现这一点,但也可以随意建议外部库。
编辑: TreeSet 不会,因为基于索引的访问很困难,使用包装器集合也不是我的最佳选择,因为删除意味着我需要从两个集合中删除。
EDIT2:我找不到indexable skip list 的实现和/或文档,这似乎有点相关,谁能帮我找到它?也欢迎任何支持或反对所提出的数据结构的 cmets。
EDIT3:虽然这可能不是最完美的答案,但我想添加我编写的这段代码,以便任何有类似问题需要排序列表的人都可以在发现它有用时使用它。
检查错误(如果有),并提出改进建议(尤其是sortedSubList 方法)
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
public class SortedList<E> extends ArrayList<E> {
private final Comparator<? super E> comparator;
public SortedList(Comparator<? super E> comparator) {
this.comparator = comparator;
}
public SortedList(int initialCapacity, Comparator<? super E> comparator) {
super(initialCapacity);
this.comparator = comparator;
}
@Override
public boolean add(E e) {
if (comparator == null)
return super.add(e);
if (e == null)
throw new NullPointerException();
int start = 0;
int end = size() - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (comparator.compare(get(mid), e) == 0) {
super.add(mid, e);
return true;
}
if (comparator.compare(get(mid), e) < 0) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
super.add(start, e);
return true;
}
@Override
public boolean contains(Object o) {
if (comparator == null)
return super.contains(o);
if (o == null)
return false;
E other = (E) o;
int start = 0;
int end = size() - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (comparator.compare(get(mid), other) == 0) {
return true;
}
if (comparator.compare(get(mid), other) < 0) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return false;
}
@Override
public int indexOf(Object o) {
if (comparator == null)
return super.indexOf(o);
if (o == null)
throw new NullPointerException();
E other = (E) o;
int start = 0;
int end = size() - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (comparator.compare(get(mid), other) == 0) {
return mid;
}
if (comparator.compare(get(mid), other) < 0) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return -(start+1);
}
@Override
public void add(int index, E e) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
@Override
public E set(int index, E e) {
throw new UnsupportedOperationException();
}
public SortedList<E> sortedSubList(int fromIndex, int toIndex) {
SortedList<E> sl = new SortedList<>(comparator);
for (int i = fromIndex; i < toIndex; i++)
sl.add(get(i));
return sl;
}
}
【问题讨论】:
-
TreeSet是你想要的 -
你应该澄清“允许我随机访问”意味着你希望它是可索引的,假设这就是你的意思。
-
很难同时获得 O(1) 索引和 O(log n) 插入/删除。 O(1) 索引将需要某种类似数组的存储,而 O(log n) 插入和删除意味着您无法在每次更新数据结构时移动一半的元素。
-
@ctomek:不是骗子。此问题具有其他问题中未包含且其答案未满足的特定、不寻常的要求。
标签: java collections sortedcollection