全部博文(37)
分类: C/C++
2011-04-27 10:44:37
哈希链表的初始化:
下面这张图包含了很多哈希链表的操作:具体的操作代码参见Source code吧。
(可以对照这张图看代码:)
hash最重要的是选择适当的hash函数,从而平均的分配关键字在桶中的位置,从而优化查找 插入和删除所用的时间。然而任何hash函数都会出现冲突问题。内核采用的解决哈希冲突的方法是:拉链法
拉链法解决冲突的做法是:将所有关键字为同义词的结点链接在同一个链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针(struct hlist_head name)组成的指针数组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α(装填的元素个数/数组长度)可以大于 1,但一般均取α≤1。
当然,用拉链法解决hash冲突也是有缺点的,指针需要额外的空间。
下面说明一下关于内核函数中经常用到的hash链表遍历的宏:
其实展开之后就是for(xxx;xxx;xxx)语句....
1)初始化条件:pos = (head)->first 指向第一个hash链表节点的指针
2)测试条件:({ prefetch(pos->next); 1;})//这个表达式的值永远为1
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); //这个表达式的值也永远为1,但是这里tpos指向了hlist_node所在的宿主结构。
测试条件只是:检测pos指针是否为空的同时,把tpos指向的hlist_node所在的宿主结构。同时预先取得指向下一个hlist_node的指针值。
3)步长:pos = pos ->next 无话可说;
fateeye2012-03-10 15:45:09
507 #define HLIST_HEAD_INIT { .first = NULL }
508 #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
509 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
510 #define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
小强,我看到这些宏我惊了.........