【问题标题】:Fastest data structure for inserting billions of integers?插入数十亿整数的最快数据结构?
【发布时间】:2021-04-28 14:25:22
【问题描述】:

我想推荐 C 中最快的数据结构,它可以容纳大约 20 亿个从输入中提取的整数。整数值不会小于 0 且不会大于 20 亿。我的目标是删除所有重复值并对数据结构的元素进行排序。如果可能的话,我希望能够在 O(1)O(logn) 中或尽可能快地进行插入操作。如果可能的话,我也想避免树木。如有任何反馈或建议,我将不胜感激。

编辑:使用普通数组需要很长时间。所以,我想使用数组以外的其他数据结构,例如堆栈、队列等。

【问题讨论】:

  • 数组是直接访问最快的。删除重复项和排序是另一回事,但您没有指定任何要求。
  • 同意。如果插入速度是您最关心的问题,请预先分配内存并使用数组。插入它们后,对其进行快速排序(O(n log n)),然后复制到预先分配的存储中,同时删除重复项(O(n))。 (我看到我已经完全重复了@dbush 对已删除问题的回答。)
  • 考虑位图:创建一个包含 2,000,000,001 位的数组(例如包含 62,500,001 个uint32_t 元素的数组)。将其初始化为零。在读取每个整数时,将其值 v 映射到数组中索引为 v 的位。设置那个位。这会自动删除重复项,因为每个位仅表示一个值至少被看到过一次。要生成排序结果,只需按顺序遍历数组并报告每个设置位。如果这些值有点均匀分布,这可能是最好的解决方案。插入是 O(1),报告是 O(n)。如果它们以某种方式聚集在一起,则可能会有所改进。
  • 您真的需要同时将所有这些都保存在内存中吗? 8Gb RAM 消耗意味着您的程序是一个非常特殊的雪花。即使是最先进的 PC 3D 游戏消耗也更少...
  • @Lundin 确实如此。可能是 XY 问题

标签: c sorting data-structures quicksort abstract-data-type


【解决方案1】:

由于您有给定数量的值,并且这些值的范围与值的数量相同,您可以将列表实现为数组,其中每个数组索引代表一个值,每个数组元素的值代表给定值是否在列表中。

例如:

char *arr = malloc(20000000001);
int i;

// populate list
memset(arr, 0, sizeof(arr));
for (i=0; i<20000000001; i++) {
    int value;
    scanf("%d", &value);
    arr[value] = 1;
}

// print list
for (i=0; i<20000000001; i++) {
    if (arr[i]) {
        printf("%d\n", i);
    }
}

这里我们将列表初始化为包含所有值的 0。然后我们读入值。如果我们读取值 n,那么我们将 arr[n] 设置为 1。这会做两件事:它将值插入列表并通过始终将值设置为 1 来消除重复项,而不是增加价值。

这给出了 O(1) 次插入和重复删除,并且列表已经排序。

还要注意,由于数组的每个元素只需要存储值 0 或 1,因此我们使用 char 作为类型来节省内存。如果我们使用每个 bit 来保存给定值的值 0 或 1,我们可以进一步节省内存。这样做会涉及一些位移:

unsigned char *arr = malloc(20000000001 / 8 + 1);
int i;

// populate list
memset(arr, 0, sizeof(arr));
for (i=0; i<20000000001; i++) {
    int value;
    scanf("%d", &value);
    arr[value/8] |= 1 << (value%8);
}

// print list
for (i=0; i<20000000001; i++) {
    if (arr[i/8] & (1 << (i%8))) {
        printf("%d\n", i);
    }
}

这将内存需求减少到大约 250MB,这仍然很大但易于管理。

【讨论】:

  • 谢谢。但是您的代码中的数组元素只有 0 或 1。虽然数字有可能是唯一的。
  • @SamuelJakes 数组元素的值只是告诉你一个数字是否在列表中,即如果 100 在列表中,那么 arr[100] 将被设置为 1。
猜你喜欢
  • 2010-11-15
  • 2019-06-21
  • 1970-01-01
  • 2011-04-07
  • 2016-01-26
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多