设为首页 加入收藏

TOP

C语言的HashTable简单实现(三)
2012-12-02 22:17:01 来源: 作者: 【 】 浏览:1006
Tags:语言 HashTable 简单 实现

 

    六,释放HASHTABLE

    hashtable的释放就比较简单了,因为我们所有的内存申请都在内存池上完成的,就只需要释放内存池,如下:

    [cpp] view plaincopy

    void hashtable_free(hashtable h)

    {

    if(h != NULL)

    pool_free(h->p);

    }

    七,释放单个hash接点

    代码如下:

    [cpp] view plaincopy

    void hashtable_delete_node(hashtable h, const char *key)

    {

    if(h == NULL || key == NULL)

    <span>  </span>return;

    hashnode node;

    int len = strlen(key);

    if(h == NULL || key == NULL || (node = hashtable_node_get(h, key, len, hashcode(key,len))) == NULL)  //没有这个接点

    return;

    node->key = NULL;

    node->val = NULL;

    h->count--;

    }

    这个就实现了一个简单的HASHTABLE结构,当然后还是有不足的,比如遍历HASHTABLE,如果用数组的方式来遍历,效率肯定很低,下面讨论一种实现方案,用于遍历hashtable.

    八,hashtable的遍历讨论

    直接用数组,就是hashtable中的struct hashnode_struct数组是可以遍历,但如果只包含一个接点,也要遍历所有的数组,如下遍历:

    [cpp] view plaincopy

    void hashtable_traverse(hashtable h)

    {

    int i;

    hashnode node;

    if(h == NULL)

    return;

    for(i = 0; i < h->prime; i++)

    for(node = &h->z[i]; node != NULL; node = node->next)

    if(node->key != NULL && node->val != NULL)

    XXXXXXXXXXXXXXXXX  // 这里是一些操作。

    }

    这样效率很低,其实在接点中包含了next域,可以用这个来实现遍历。

    需要对前面hashtable数据结构做简单的改动,增加两个域:

    [cpp] view plaincopy

    typedef struct hashtable_struct{

    pool_t p;

    int size;

    int count;

    struct hashnode_struct *z;

    int bucket;

    hashnode node;

    }*hashtable,_hashtable;

    就是增加了bucket和node两个域,加这两个域的思路是这样的:

    node表示当前遍历的游标,在遍历过程中,不断的移动这个接点所指向的接点。

    bucket是和node相关联的,用于记录当前的node在哪个桶上。

    首先建立连接,就是将所有的接点都连接起来,按照惯例,也采用XXX_iter_first函数,先初始化,如下:

    [cpp] view plaincopy

    int hashtable_iter_first(hashtable h) {

    if(h == NULL)

    <span>  </span>return 0;

    h->bucket = -1;

    h->node = NULL;

    return hashtable_iter_next(h);

    }

    hashtable_iter_next用于获取下一个接点,如果这时游标已经确定,那下一个接点就会被很快的被确定,定义如下:

    [cpp] view plaincopy

    int xhash_iter_next(xht h) {

    if(h == NULL) return 0;

    while(h->node != NULL) {

    h->node = h->node->next;   // 移向下一个接点,如果接点合法,返回成功

    if(h->node != NULL && h->node->key != NULL && h->node->val != NULL)

    return 1;

    }

    for(h->bucket++; h->bucket < h->prime; h->bucket++) {

    h->node = &h->z[h->bucket];

    while(h->node != NULL) {

    if(h->node->key != NULL && h->node->val != NULL)

    return 1;

    h->node = h->node->next;

    }

    }

    h->bucket = -1;  // 不存在下一个接点。

    h->node = NULL;

    return 0;

    }

    有了上面两个方法之后,遍历操作如下:

    [cpp] view plaincopy

    hashtable ht

    if(hashtable_iter_first(ht))   //取第一个接点。

    do{

    // 此时可以处理ht->node,表示当前的接点。

    }while(hashtable_iter_next(ht));  //取下一个接点

    这样处理的话, 是不是高效多了。当然在第一遍的时候,还是需要遍历整个数组和数组下的桶中接点。不过这样操作之后,在删除一个结点的时候,就需要做一些操作。删除一个接点时,需要考虑当前的h->node是不是当前被删除的接点,如果是,就把h->node称至下一个接点。就是删除之后,要作如下处理,假如删除了。

    假如被删除的接点为node,需要如下处理:

    [cpp] view plaincopy

    if(h->node == n)

    hashtable_iter_next(h);

    将h->node移动到下一个接点。

      

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C小程序 - setbuf和set.. 下一篇C语言中结构体的的慨念和使用方法

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: