当索引不是连续的时,设置查找表的最佳方法是什么?

时间:2013-03-12 03:27:50

标签: c

我这样定义了两个枚举

enum foo {
    foo_a = 0x1,
    foo_b = 0x2,
    foo_c = 0x4,
    foo_d = 0x8,
    foo_e = 0x10,
    ..etc..
}

enum bar {
    bar_a = 0x1,
    bar_b = 0x2,
    bar_c = 0x4,
    bar_d = 0x8,
    bar_e = 0x10,
    ..etc..
}

现在,foo_ [az]和bar_ [az]之间存在1到1的映射,我想快速查找一下。显而易见的方法是做一些声明类似

的事情
int table[][] = {
    [foo_a] = bar_c,
    [foo_b] = bar_a,
    [foo_c] = bar_b,
    ..etc..
}

然后使用result = table[(enum foo)temp]查找。但由于这些枚举已经按位声明,因此table的大小呈指数级增长。

有没有更简单的方法在编译时设置?

我考虑过做一件像

这样的事情
int table[][] = {
    [LOG(foo_a)] = bar_c,
    [LOG(foo_b)] = bar_a,
    [LOG(foo_c)] = bar_b,
    ..etc..
}

这会减少内存占用,但我还是不知道在编译时计算LOG。

还有其他建议吗?

我唯一的限制是以下内容,我无论如何都无法修改枚举,因为更改它们会导致二进制不兼容。

编辑:首选编译时解决方案

3 个答案:

答案 0 :(得分:3)

是的,只要参数是2的幂,就可以“在编译时计算日志”:

#define LOG2P2(m) (((m)-1)/(((m)-1)%255+1) / 255%255*8 + 7-86/(((m)-1)%255+12))

这适用于m到2 * 2040左右的值(比实际C实现中的任何类型都要大得多),并且有一个适用于更大值的版本,我从,在回答以下问题时:

https://stackoverflow.com/a/4589384/379897

答案 1 :(得分:1)

只需制作成对表:

int table[2][] = {
  { foo_a, bar_c },
  { foo_b, bar_a },
  /* ... */
};

现在对它进行排序,如果需要,将其复制到第二个表,该表按第二个值排序以进行反向查找。如果表格只有十几个元素,则进行线性搜索;如果表格很大,则使用bsearch()

答案 2 :(得分:0)

如果您知道所有枚举的值,那么您可以计算所有枚举的日志并将它们存储在缓冲区中。或者,您可以编写所有日志。值(您将要使用)在文件中并读取该文件以生成表;以这种方式,你将计算日志。值只是第一次。