【问题标题】:A set that maintains insert order and allows accessing elements by its index维护插入顺序并允许通过索引访问元素的集合
【发布时间】:2012-03-15 05:29:09
【问题描述】:

我基本上需要一个像Set 一样工作的数据结构,但它不仅维护插入顺序,让我稍后通过get(index) 方法获取它们。

最适合实现这一目标的数据结构是什么?如果需要,我不必实施一个问题。在更糟糕的情况下,我可以同时使用 ArrayList 和 HashSet,但我想知道是否有专门的数据结构来完成这项任务。

性能是最重要的(否则我可以在常规列表上进行 O(n) 搜索!)而且我并不担心空间复杂性。

【问题讨论】:

  • 两个数据结构怎么样:一个将索引映射到项目的字典和一个项目的哈希图。
  • 你需要 C# 还是 Java 中的这种数据结构?
  • Guava 有 considered this,但我们找不到真正需要它的人。您介意在此处详细介绍您的用例吗?
  • 哦,这是针对旅行推销员问题的蛮力实现,所以我承认这不是一个真正的标准场景。

标签: c# java data-structures set


【解决方案1】:

OrderedDictionary 怎么样?

表示可由 键或索引。

http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx

【讨论】:

  • 啊。我没有意识到这一点。这是算法的通用名称吗?
  • @devouredelysium 我链接的特定一个是 c# 集合类型。
  • 我知道。但是我很担心找到一个现有的实现,就像知道背后使用的算法的名称一样(这是针对算法和数据结构研究生课程的)。
  • @devouredelysium 那我不太确定。可以尝试一些谷歌搜索看看,和/或用反射器戳它的胆量,看看它是如何实现的。
【解决方案2】:

这样的? 编辑:正如 Jiddo 所指出的,这种结构不能有效地删除元素。如果不需要有效的移除,ArrayList + Set 会更简单,因此这种结构实际上并没有多大用处。

import java.util.*;

public class ArraySet<T> {
    private final Map<Integer, T> indexToElem;
    private final Map<T, Integer> elemToIndex;

    public ArraySet() {
        indexToElem = new HashMap<Integer, T>();
        elemToIndex = new HashMap<T, Integer>();
    }

    public T get(int index) {
        if (index < 0 || index >= size())
            throw new IndexOutOfBoundsException();
        return indexToElem.get(index);
    }

    public void add(T elem) {
        if (!contains(elem)) {
            int index = indexToElem.size();
            indexToElem.put(index, elem);
            elemToIndex.put(elem, index);
        }
    }

    // Doesn't work; see comment.
    /*public void remove(T elem) {
        int index = elemToIndex.get(elem);
        indexToElem.remove(index);
        elemToIndex.remove(elem);
    }*/

    public boolean contains(T elem) {
        return elemToIndex.containsKey(elem);
    }

    public int size() {
        return indexToElem.size();
    }
}

【讨论】:

  • 不错。但这是否比 set+arraylist 组合更好?
  • 我不明白您将如何有效地从 ArrayList 中删除,移动其他元素不会花费线性预期时间吗?
  • 啊,忘了那个小细节了。
  • 请注意,使用建议的实现,对除最后一个元素之外的任何元素的删除操作都会有效地破坏集合。无法检索最后一个元素,下一个添加元素的索引将与最后一个元素发生冲突,并且可访问的索引将不再连贯。如果不需要删除,那么它可以正常工作。
  • @Jiddo 好点,我忽略了这一点。这个答案可能不应该被接受。平衡树,其中每个节点存储其后代计数,似乎是更好的方法。那应该能够在对数时间内完成所有操作。
【解决方案3】:

您愿意使用现有代码吗? Apache Commons 有一个 ListOrderedSet 类,似乎满足您的所有要求。最糟糕的是,你可以研究源代码并用 C# 实现。

【讨论】:

  • 非泛型!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!但是,谢谢,似乎正是我正在寻找的。我也会看看它的来源。
猜你喜欢
  • 2013-01-06
  • 2011-04-11
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多