key值最多膨胀64倍,查找时间复杂度为len(key)*4的hash_map

haoruixiang 2016-06-03 03:21:46
常用的字符串hash算法是根据字符串算出一个整数,再根据这个整数进行存储(http://blog.csdn.net/djinglan/article/details/8812934),而整数的hash一般是定义一个很大的空间,而进行一次性hash,浪费空间很严重,而且计算出来的整数不能保证唯一性,有可能是重复的。

根据key,value的特性,我设计了一种新的方式去定位字符串,这种方法所需要的空间不是很大,每个key都有唯一,查找复杂度也是固定不变的,就是key的长度。

首先:
一个字节的范围0~255,对字节进行编码,最简单的是256进制编码,一个256的数组,字节就可以直接定位了,例如:

struct node{
void * node[256]
};
node head;
char * key = "sdada";
char * p = key;
node * pnode = &head;
void * data = 0;
do{
unsigned char c = p[0];
data = pnode->node[c];
p++;
if (!p[0]){ break;}
pnode = (node*)data;
}while(false);

当然实际中,会比这段代码复杂,需要将键值和数据分开。
key = "sdada"只要查找5次就能找到值了,这里有个缺点一个字节膨胀了256*4 = 1024倍。即膨胀系数为1024

256是16的平方倍数,我们可以用16进制编码:
struct node{
void * node[16]
};
node head;
char * key = "sdada";
char * p = key;
node * pnode = &head;
void * data = 0;
do{
unsigned char c = p[0];
int index1 = c/16;
int index2 = c%16;
pnode = (node*)pnode->node[index1];
data = (node*)pnode->node[index2];
p++;
if (!p[0]){ break;}
pnode = (node*)data;
}while(false);

进行16进制编码后,发现字节膨胀系数变成 (16+16)*4 = 128,膨胀系数128比1024少了许多,只是查找次数是256编码的2倍,但是这是可以接受的。
后面还实验了对字节进行4进制编码:
结果:膨胀系数为 (4+4+4+4)*4 = 64 ,查找次数为16进制的2倍,256进制的4倍
2进制编码:
结果:膨胀系数为 (2+2+2+2+2+2+2+2)*4 = 64 与4进制相同,查找次数为4进制的2倍,256进制的8倍。
这种几种编码还有一种因素,那就是节点复用率,经测试发现,节点复用率 2进制编码 》4进制编码 =》16进制编码 =》256进制编码。

测试例子:

time_t t = time(0);
hdc_hash_map map;
for (int i = 0; i <1000000; i++)
{
int sas = i;
map.set((const char*)(&sas),sizeof(int),0);
}
printf("%ld\n",time(0)-t);

100万个key, 每个key长度为4字节,用4进制编码进行hash,计算需要(1000000*64*4)= 244M的空间,实际占用108M,花费时间2s时间。

我个人建议:对字符进行4进制编码,进行hash最划算,膨胀系数:64,查找次数为key长度的4倍,还有节点复用率也不错,具体需要做详细测试。


...全文
154 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
haoruixiang 2016-06-06
  • 打赏
  • 举报
回复
static int hdc_pe4[256][4] = {
    {0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,0,3},
    {0,0,1,0},{0,0,1,1},{0,0,1,2},{0,0,1,3},
    {0,0,2,0},{0,0,2,1},{0,0,2,2},{0,0,2,3},
    {0,0,3,0},{0,0,3,1},{0,0,3,2},{0,0,3,3},
    {0,1,0,0},{0,1,0,1},{0,1,0,2},{0,1,0,3},
    {0,1,1,0},{0,1,1,1},{0,1,1,2},{0,1,1,3},
    {0,1,2,0},{0,1,2,1},{0,1,2,2},{0,1,2,3},
    {0,1,3,0},{0,1,3,1},{0,1,3,2},{0,1,3,3},
    {0,2,0,0},{0,2,0,1},{0,2,0,2},{0,2,0,3},
    {0,2,1,0},{0,2,1,1},{0,2,1,2},{0,2,1,3},
    {0,2,2,0},{0,2,2,1},{0,2,2,2},{0,2,2,3},
    {0,2,3,0},{0,2,3,1},{0,2,3,2},{0,2,3,3},
    {0,3,0,0},{0,3,0,1},{0,3,0,2},{0,3,0,3},
    {0,3,1,0},{0,3,1,1},{0,3,1,2},{0,3,1,3},
    {0,3,2,0},{0,3,2,1},{0,3,2,2},{0,3,2,3},
    {0,3,3,0},{0,3,3,1},{0,3,3,2},{0,3,3,3},
    {1,0,0,0},{1,0,0,1},{1,0,0,2},{1,0,0,3},
    {1,0,1,0},{1,0,1,1},{1,0,1,2},{1,0,1,3},
    {1,0,2,0},{1,0,2,1},{1,0,2,2},{1,0,2,3},
    {1,0,3,0},{1,0,3,1},{1,0,3,2},{1,0,3,3},
    {1,1,0,0},{1,1,0,1},{1,1,0,2},{1,1,0,3},
    {1,1,1,0},{1,1,1,1},{1,1,1,2},{1,1,1,3},
    {1,1,2,0},{1,1,2,1},{1,1,2,2},{1,1,2,3},
    {1,1,3,0},{1,1,3,1},{1,1,3,2},{1,1,3,3},
    {1,2,0,0},{1,2,0,1},{1,2,0,2},{1,2,0,3},
    {1,2,1,0},{1,2,1,1},{1,2,1,2},{1,2,1,3},
    {1,2,2,0},{1,2,2,1},{1,2,2,2},{1,2,2,3},
    {1,2,3,0},{1,2,3,1},{1,2,3,2},{1,2,3,3},
    {1,3,0,0},{1,3,0,1},{1,3,0,2},{1,3,0,3},
    {1,3,1,0},{1,3,1,1},{1,3,1,2},{1,3,1,3},
    {1,3,2,0},{1,3,2,1},{1,3,2,2},{1,3,2,3},
    {1,3,3,0},{1,3,3,1},{1,3,3,2},{1,3,3,3},
    {2,0,0,0},{2,0,0,1},{2,0,0,2},{2,0,0,3},
    {2,0,1,0},{2,0,1,1},{2,0,1,2},{2,0,1,3},
    {2,0,2,0},{2,0,2,1},{2,0,2,2},{2,0,2,3},
    {2,0,3,0},{2,0,3,1},{2,0,3,2},{2,0,3,3},
    {2,1,0,0},{2,1,0,1},{2,1,0,2},{2,1,0,3},
    {2,1,1,0},{2,1,1,1},{2,1,1,2},{2,1,1,3},
    {2,1,2,0},{2,1,2,1},{2,1,2,2},{2,1,2,3},
    {2,1,3,0},{2,1,3,1},{2,1,3,2},{2,1,3,3},
    {2,2,0,0},{2,2,0,1},{2,2,0,2},{2,2,0,3},
    {2,2,1,0},{2,2,1,1},{2,2,1,2},{2,2,1,3},
    {2,2,2,0},{2,2,2,1},{2,2,2,2},{2,2,2,3},
    {2,2,3,0},{2,2,3,1},{2,2,3,2},{2,2,3,3},
    {2,3,0,0},{2,3,0,1},{2,3,0,2},{2,3,0,3},
    {2,3,1,0},{2,3,1,1},{2,3,1,2},{2,3,1,3},
    {2,3,2,0},{2,3,2,1},{2,3,2,2},{2,3,2,3},
    {2,3,3,0},{2,3,3,1},{2,3,3,2},{2,3,3,3},
    {3,0,0,0},{3,0,0,1},{3,0,0,2},{3,0,0,3},
    {3,0,1,0},{3,0,1,1},{3,0,1,2},{3,0,1,3},
    {3,0,2,0},{3,0,2,1},{3,0,2,2},{3,0,2,3},
    {3,0,3,0},{3,0,3,1},{3,0,3,2},{3,0,3,3},
    {3,1,0,0},{3,1,0,1},{3,1,0,2},{3,1,0,3},
    {3,1,1,0},{3,1,1,1},{3,1,1,2},{3,1,1,3},
    {3,1,2,0},{3,1,2,1},{3,1,2,2},{3,1,2,3},
    {3,1,3,0},{3,1,3,1},{3,1,3,2},{3,1,3,3},
    {3,2,0,0},{3,2,0,1},{3,2,0,2},{3,2,0,3},
    {3,2,1,0},{3,2,1,1},{3,2,1,2},{3,2,1,3},
    {3,2,2,0},{3,2,2,1},{3,2,2,2},{3,2,2,3},
    {3,2,3,0},{3,2,3,1},{3,2,3,2},{3,2,3,3},
    {3,3,0,0},{3,3,0,1},{3,3,0,2},{3,3,0,3},
    {3,3,1,0},{3,3,1,1},{3,3,1,2},{3,3,1,3},
    {3,3,2,0},{3,3,2,1},{3,3,2,2},{3,3,2,3},
    {3,3,3,0},{3,3,3,1},{3,3,3,2},{3,3,3,3}
};
这是每个字节固定的查找或者建树的规则。
haoruixiang 2016-06-06
  • 打赏
  • 举报
回复
在网上查了资料,与我介绍的这种不同吧, 我设计的是一种树形的存储结构: ,每棵字节树含有256个节点,data节点后面再接入下一个字节树,数据存储的时候按照规则建树,查询的时候只要按照规则查询就行了。
赵4老师 2016-06-03
  • 打赏
  • 举报
回复
搜“暴雪哈希算法”

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧