【问题标题】:Looking for a data structure which provides both random and "sequential" access寻找提供随机和“顺序”访问的数据结构
【发布时间】:2015-12-27 15:29:40
【问题描述】:

这是我经常遇到的一个编程问题,我想知道是否存在一种数据结构,无论是在 C++ STL 中还是我可以自己实现的同时提供随机和顺序访问的数据结构。

我可能需要这个的一个例子:

  • 假设有 n 种物品,(例如,n = 1000000),每种物品的数量是固定的(例如,0 或 10)

  • 我将这些项目存储到一个数组中,其中数组索引表示项目的类型,值表示该给定类型的项目有多少

  • 现在,我有一个迭代所有现有项目的算法。要获取这些项,除了Array[99999]和Array[999999]之外,在所有项都为0的情况下遍历整个数组是非常浪费的。

通常,我通过使用保存所有非零数组条目的索引的链表来解决这个问题。我是这样实现标准操作的:

插入(int t):

1) 如果 Array[t] == 0,LinkedList.push_back(t);

2) 数组[t]++;

删除(int t):

1) 如果 Array[t] == 1,则从 LinkedList 中查找并删除 t;

2) 数组[t]--;

如果我希望删除操作的复杂度为 O(1),我让数组存储容器而不是整数。每个容器都包含一个整数和一个指向 LinkedList 的相应元素的指针,因此我不必在列表中搜索。

我很想知道是否有一种数据结构可以形式化/改进这种方法,或者是否有更好的方法来完全做到这一点。

【问题讨论】:

  • 我认为使用 unordered_map(具有 O(1) 平均查找的哈希图)代替链表将达到您想要的运行时间。
  • 您需要按顺序进行迭代吗?如果没有,std::unordered_map 从类型到计数怎么样?
  • std::map 与数组和 unordered_map 组合相比,存在运行时间较慢的问题
  • 内存复杂度和运行时复杂度之间存在折衷。
  • 如果您需要对整个集合进行快速迭代(如要点 3 中所述)尝试使用包含对象的 map/unordered_map,然后将它们全部引用到向量中(或类似的,快速迭代动态数组)作为 Object* 。这使您可以通过键快速访问成员,并根据索引快速迭代所有成员。

标签: c++ data-structures stl


【解决方案1】:

鉴于以下要求:

  • 随机访问
  • 快速查找
  • 快速插入
  • 快速移除
  • 避免浪费空间

那么你可能想要一个叫做sparse array的东西。 稀疏数组不是标准库的一部分,因此您必须使用std::mapstd::unordered_map 模拟自己的数组。在稀疏数组中,只有非零元素会占用集合中的空间。

ordered_map 将有 O(1) 次查找、插入和删除,但不提供有序迭代。 map 通常会有较慢的操作,但会提供有序迭代。当我说std::map 速度较慢时,我过于简单化了,因为它取决于元素的数量和使用模式(一个主题可能已经在另一个问题中讨论过)。

如果您必须绝对同时拥有 O(1) 查找和有序迭代,那么您可以将 mapordered_map 结合起来并保持它们同步。届时,您将需要考虑使用Boost.MultiIndex

这是一个粗略的草图,展示了如何实现自己的稀疏向量类:

class SparseVector
{
public:
    int get(size_t index) const
    {
        auto kv = map_.find(index);
        return (kv == map_.end()) ? 0 : kv->second;
    }

    void put(size_t index, int value)
    {
        if (value == 0)
            map_.erase(index);
        else
            map_.emplace(index, value);
    }

    // etc...

private:
    std::unordered_map<size_t, int> map_;
};

在这样一个稀疏向量类中,如果您希望允许类似 sparseVec[42] = 123 的内容,可以重载 operator[]

线性代数库,例如EigenBoost.uBlas,已经为稀疏向量和稀疏矩阵提供了模板。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多