【问题标题】:Ideal data structure for mapping integers to integers?将整数映射到整数的理想数据结构?
【发布时间】:2009-11-24 02:12:13
【问题描述】:

我不会详细介绍,但我正在尝试实现类似于Boyer-Moore-Horspool algorithm 的算法,仅使用十六进制颜色值而不是字符(即范围更大)。

按照维基百科上的示例,我最初有这个:

size_t jump_table[0xFFFFFF + 1];
memset(jump_table, default_value, sizeof(jump_table);

然而,0xFFFFFF 显然是一个 巨大 数字,这很快会导致 C 出现段错误(但不是堆栈溢出,令人失望)。

基本上,我需要的是一个高效的关联数组,将整数映射到整数。我正在考虑使用哈希表,但对每个条目都有一个 malloc 的结构对我来说似乎有点过头了(我也不需要生成哈希,因为每个键都是一个唯一的整数,并且不能有重复的条目)。

有没有人可以提出任何替代方案?我是不是太务实了?

更新

对于那些感兴趣的人,我最终通过uthash 库使用了一个哈希表。

【问题讨论】:

    标签: c algorithm data-structures


    【解决方案1】:

    0xffffff 在大多数系统上都太大而无法放入堆栈,但您绝对可以malloc 使用该大小的缓冲区(至少在当前的计算机上;在智能手机上没有那么多)。你是否应该为这项任务做这件事是一个单独的问题。

    编辑:根据评论,如果您希望常见情况除了“此颜色未出现在输入中”跳过值之外的条目数量相对较少,您应该可能只是继续使用哈希映射(显然只存储实际出现在输入中的值)。

    (忽略之前对其他数据结构的讨论,这是基于对所讨论算法的错误回忆——你想使用哈希表)

    【讨论】:

    • 这取决于输入。根据输入缓冲区的大小,它可能少至 10 或多至 1,764,000(或理论上 0xFFFFFF = 16,777,216,但这是非常罕见的情况)。
    【解决方案2】:

    如果您要创建的数组(大小为 0xFFFFFF)将是稀疏的,您可以尝试制作一个较小的数组来充当简单的哈希表,大小为 0xFFFFFF / N,哈希函数为 @987654322 @(或hexValue % (0xFFFFFF / N))。不过,您必须有创造力才能处理碰撞。

    这是我可以预见离开mallocing structs 的唯一方法。

    【讨论】:

    • 对不起,如果我太密集了,但是你说的 N 是什么意思?输入中的颜色数量?
    • N 只是您选择的标量。它只需要足够大,一个 0xFFFFFF / N 整数的数组就可以放在堆栈上。 0xFFFFFF 整数等于 64MB(假设是 32 位整数),gcc 的默认堆栈大小为 8MB IIRC。
    【解决方案3】:

    您可以在堆上 malloc(3) 0xFFFFFF 个 size_t 块(为简单起见),并像处理数组一样处理它们。

    至于堆栈溢出。基本上程序会收到一个 SIGSEGV,这可能是堆栈溢出或访问非法内存或写入只读段等的结果......它们都在相同的错误消息“Segmentation fault”下抽象出来。

    但是为什么不使用支持关联数组的高级语言,例如 python?

    【讨论】:

      【解决方案4】:

      可能会以一些速度为代价,您可以尝试修改算法以仅查找与某个边界对齐的匹配项(每三个或四个符号),然后在字节级别执行搜索。

      【讨论】:

        【解决方案5】:

        你可以创建一个稀疏的排序数组,其中包含这样的“页面”(本示例使用 256 个“页面”,因此最高字节是页码):

        int *pages[256]; 
        
        /* call this first to make sure all of the pages start out NULL! */
        void init_pages(void) {
            for(i = 0; i < 256; ++i) {
                pages[i] = NULL;
            }
        }
        
        int get_value(int index) {
            if(pages[index / 0x10000] == NULL) {
                pages[index / 0x10000] = calloc(0x10000, 1); /* calloc so it will zero it out */
            }
            return pages[index / 0x10000][index % 0x10000];
        }
        
        void set_value(int index, int value) {
            if(pages[index / 0x10000] == NULL) {
                pages[index / 0x10000] = calloc(0x10000, 1); /* calloc so it will zero it out */
            }
            pages[index / 0x10000][index % 0x10000] = value;
        }
        

        这将在第一次被触摸、读取或写入时分配一个页面。

        【讨论】:

          【解决方案6】:

          为了避免 malloc 的开销,您可以使用哈希表,其中表中的条目是您的结构,假设它们很小。在您的情况下,一对整数就足够了,并带有一个特殊值来指示表中的插槽为空。

          【讨论】:

            【解决方案7】:

            您的输出空间中有多少个值,即您在 0-0xFFFFF 范围内映射到多少个不同值?

            使用randomized universal hashing,您可以提出一个无冲突的哈希函数,其表不大于输出空间中值数量的 2 倍(对于静态表)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-11-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-31
              • 2020-12-17
              • 2010-09-05
              相关资源
              最近更新 更多