处理大数据集,需要维护原始数据集

Large Data Set for Processing, need to maintain original data set

本文关键字:数据集 维护 原始 原始数据 处理      更新时间:2023-10-16

这是我的问题定义:我有一个包含 700万个索引的数组,每个索引都包含一个标签。为了简单起见,这里有一个我要处理的数组示例:[1 2 3 3 3 5 2 1 7]。

我需要遍历这个数组,每次遇到标签时,将标签的位置与所有其他相同标签的位置一起输入到"set"中。由于数组如此之大,我只想在任意给定的点上访问特定标签的位置,比如说,我只想访问3的位置并处理这些位置并将它们更改为5,但我想做的不仅仅是一个操作,不仅如此,我想对所有标签分别进行操作。在像我的例子这样的小数组中,仅仅坚持使用数组似乎是微不足道的。然而,对于一个有700万个点的数组,完成对所述标签的搜索并对其进行操作要花费更多的时间。

为了消除混淆,使用我的示例,我希望示例数组给我以下内容:

  • 1映射到包含0和7的集合
  • 2映射到包含1和6的集合
  • 3映射到包含2、3和4的集合
  • 5映射到包含5
  • 的集合

最初,我在原始数组上进行处理,并简单地对数组进行操作。这大约需要~30秒来确定每个标签对应的索引数(所以我能够确定1的大小为2,6的大小为2,3的大小为3,等等)。然而,它并没有使用这种方法产生所述标签的位置。因此,在我的其余处理过程中,找到每个标签的位置也增加了时间,尽管通过添加终止(一旦找到引用标签的所有索引,就停止搜索)可以加快速度。

下一步,我使用map<int,set<int>>,但这最终导致时间增加到~100秒,但减少了后续处理的时间,但不足以证明时间的大量增加。

我还没有实现它,但作为一个额外的步骤,我计划尝试初始化一个集合数组,索引对应于标签,并尝试用这种方法来做。

我也尝试过hash_maps,但无济于事。Unordered_sets和unordered_maps不包含在Visual Studio 2005的STL中,所以我没有使用这两个结构实现上述内容。

重点:我已经对数组进行了预处理,这样我就知道最大标签,并且所有标签都是连续的(最小标签和最大值之间没有间隔)。但是,它们在原始数组中是随机分布的。这在初始化一个固定大小的数据结构时很有用。与标签对应的索引的顺序并不重要。标签在给定数据结构中的顺序也不重要。

编辑:对于背景,数组对应于一个二进制图像,我实现了二进制顺序标记,以输出一个与UINT16二进制图像相同大小的数组,其中所有二进制blobs都被标记。我现在想做的是尽可能高效地获得组成每个blob的点的映射

为什么要使用如此复杂的数据结构?只是创建一个向量的向量来存储每个标签的所有位置,就这样。您还可以通过预处理每个标签需要多少空间来避免恼人的矢量内存分配。像这样:

vector <int> count(N);
for(size_t i = 0; i < N; ++i)
    ++count[dataArray[i]];
vector < vector <int> > labels(N);
vector <int> last(N);
for(size_t i = 0; i < N; ++i)
    labels[i].resize(count[i]);
for(size_t i = 0; i < N; ++i) {
    labels[dataArray[i]][last[dataArray[i]]] = i;
    ++last[dataArray[i]];
}

它将在O(N)时间内运行,对于您的700万个整数来说,这看起来像是1秒。

我不一定会使用通用映射(或哈希表)。

我最初的直觉是,我将创建第二个数组"positions",包含700万个(或任意N个)位置,并创建第三个数组"last_position_for_index",对应于范围[min-label, max-label]。请注意,这几乎肯定会比任何类型的map占用更少的存储空间。

初始化last_position_for_index的所有条目为某个保留值,然后您可以使用类似(未经测试)的内容遍历数组:

for (std::size_t k = 0; k<N; ++k) {
  IndexType index = indices[k];
  positions[k] = last_position_for_index[index-min_label];
  last_position_for_index[index-min_label] = k;
}