如何解决正在检查大型订购清单中的成员资格?
我在C中有一段代码可以顺序生成许多数字,我想检查这些数字是否在排序列表中。该列表是使用numpy创建的,并且具有〜10 9 个元素,如上所述,这些元素的排列顺序为从最小到最大。 C代码检查其结果是否在此列表中的最快最快方法是什么?我应该使用哪种数据结构(如果包含C ++ STL)?我当时以为在无序地图上进行二进制搜索可能最快,但是我不确定。
此外(这可能是最重要的事情),我该如何在程序中包括数字列表-只需将其复制并粘贴到文件中即可?还是冒险进入sqlite或其他数据库?
解决方法
理论上最快的方法(实际上也可能是实践中的方法)是O(1):使用位图,即std::vector<bool>
(具有特殊的实现,每个条目仅使用一位)。仅当且仅当位i
在原始列表中时,才将其设置为true。这使您可以通过单个内存提取来执行检查。缺点是,这可能会花费比您更多的内存,具体取决于列表中的最大数量。
如果不合适,可以考虑std::set
(O(n log n)),std::unordered_set
(O(1))或经过排序的std::vector
进行二进制搜索( O(n log n))。测量一下哪个最快。
如果仍然不够出色,您还可以考虑使用Bloom filter作为快速检查来排除许多未命中的对象,然后再开始进行较慢的搜索。
,您的数组已排序。只需将 C 标准库bsearch
函数与 array 结合使用。如果您是用Numpy制作的,则将它们作为 binary ,按顺序(即
import numpy as np
array = np.arange(1,3000000,3,dtype='int32')
array.tofile('array.bin')
,如果在Unix / Linux中,则使用mmap
将其映射到内存中,只读:
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
int cmpfunc(const void *a,const void *b)
{
const int32_t *A = a,*B = b;
return (*A > *B) - (*A < *B);
}
bool is_in_array(int32_t *base,size_t length,int32_t element) {
return bsearch(&element,base,length,sizeof (int32_t),cmpfunc);
}
int main(void) {
int fd = open("array.bin",O_RDONLY);
struct stat statbuf;
fstat(fd,&statbuf);
size_t length = statbuf.st_size;
void *base = mmap(NULL,PROT_READ,MAP_SHARED,fd,0);
size_t elements = length / sizeof(int32_t);
for (int32_t i = 0; i < 3 * elements; i += 10000) {
printf("%" PRId32 " is %sin the set\n",i,is_in_array(base,elements,i) ? "" : "not ");
}
munmap(base,length);
close(fd);
}
bsearch
不一定绝对最快,但是也不错。如果速度太慢,则可以考虑内联算法。
如果数字范围确实小到0到1.3G,则可以将其组织为位图。但是,如果您的数字是int64或md5哈希值,则位图将不起作用。
对于位图,您可以使用
import numpy as np
array = np.arange(1,dtype='int32')
bytearray = np.zeros(array.max() + 1,dtype='bool')
bytearray[array] = 1
bitarray = np.packbits(bytearray)
bitarray.tofile('bitarray.bin')
和:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
int main(void) {
struct stat statbuf;
int fd = open("bitarray.bin",O_RDONLY);
fstat(fd,&statbuf);
size_t length = statbuf.st_size;
unsigned char *base = mmap(NULL,0);
size_t limit = length * CHAR_BIT;
for (size_t i = 0; i < limit + 30000; i += 10000) {
bool is_in = false;
if (i < limit) {
size_t index = i / CHAR_BIT;
int bit = i % CHAR_BIT;
is_in = (base[index] & (1 << bit));
}
printf("%" PRIu32 " is %sin the set\n",is_in ? "" : "not ");
}
munmap(base,length);
close(fd);
}
当然,最简单的就是在Python中做这两种事情-Numpy的二进制搜索形式为searchsorted
。
在C代码中,我将使用一个无符号整数的简单数组,并让每个位代表一个数字。这将需要大约。 200MB的内存。如果您的系统具有8G,并且这是唯一正在运行的程序,那么我认为200MB的价格对于快速查找是合理的。
查找功能可以简单地是:
bool check(uint32_t value,uint32_t* arr)
{
uint32_t tmp = arr[value >> 5];
return tmp & (1 << (value & 0x1F));
}
您刚放置在启动时读取的txt文件中的Numpy数据。
对于Numpy中的每个值,请调用以下函数:
void set(uint32_t value,uint32_t* arr)
{
uint32_t idx = value >> 5;
arr[idx] = arr[idx] | (1 << (value & 0x1F));
}
在插入任何Numpy值之前,请使用calloc
动态分配数组。喜欢:
uint32_t numpyVal;
uint32_t* arr = calloc(MAX_NUM/32,sizeof *arr);
while(getNextNumpyValue(&numpyVal)
{
set(numpyVal,arr);
}
if (check(SOME_VALUE,arr)
{
printf("Found\n");
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。