微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

陷入重新哈希我在 C 中使用 Hashtable 实现的字典

如何解决陷入重新哈希我在 C 中使用 Hashtable 实现的字典

我已经用c语言实现了这个哈希表字典。它在没有重新散列功能的情况下工作正常。 现在, 我正在尝试为其添加一个重新哈希函数,它允许每次负载因子超过 0.75 时重新哈希它。但它不能正常工作。我需要这方面的帮助..告诉我我做错了什么?

字典和列表结构在这里

//List of bins
struct list {
    char *key;
    unsigned long hash;
    void *user_data;
    struct list *next;
};

//Main hash table Dictionary
struct dict {
    struct list **bins;
    unsigned int nbins;
    unsigned long int count;    /* for rehashing - for calculation load factor */
    void (*deleter)(void *user_data);
};

这些是我记录的重新散列的步骤。

1. malloc() 一个两倍大的新 bin 数组

newNumberOfBin = D->nbins;

2.将所有列表节点移动到新数组

  -Get Stored hash 

  -Calulate new bin number of list node as

int newBinNo = hash % newNumberOfBin;

  -Move node to new bin

3.免费的旧 bin 数组

4.更新 struct dict 成员

  -bin will point to new_bins
 
  -nbins will be updated

rehash 函数如下所示

static int dict_rehash(struct dict *D)
{

    int idx;
    int new_idx;

    unsigned int new_nbins; 
    struct list **new_bins;

    struct list *cur;

    //This block is just for debugging purpose..its working fine
    #if DEBUG
        /* print # of items in each bin */
    dict_debug_bin_fill(D);
    fprintf(stderr,"Rehashing...\n");
        /* pause for 3 seconds */
    sleep(3);
    #endif


    new_nbins = D->nbins*2; 
    new_bins = malloc(new_nbins*sizeof(*D->bins));

    for (idx=0; idx<D->nbins; idx++) {
        
        for(cur=D->bins[idx]; cur; cur=cur->next) {

               new_idx =  cur->hash%new_nbins;
               struct list *cur2 = new_bins[new_idx];

                    while(cur2 != NULL){
                        cur2=cur2->next;
                    }

                    cur2 = cur;
        }
    }

    free(D->bins);
    D->bins = new_bins;
    D->nbins = new_nbins;


    return 0;
}

我需要帮助,我在这功能中哪里出了问题?

解决方法

在您的代码中,您遍历新 bin 中的列表,然后重新分配一个局部变量,它不会对您的实际列表执行任何操作。当您删除旧 bin 并将新 bin 列表附加到哈希表时,节点仍位于旧 bin 中并且无法访问。

相反,对于每个旧 bin,当 bin 的列表不为空时,提取其头部。找到新的 bin 并将提取的节点插入到它的头部。 (垃圾箱中物品的顺序在这里无关紧要。)

提取第一个节点很容易:保存节点并将头部设置为下一个节点。在列表的头部插入也很容易:将节点的链接设置为头部,然后将头部设置为插入的节点。

所以:

static int dict_rehash(struct dict *D)
{
    unsigned int new_nbins = D->nbins * 2; 
    struct list **new_bins = malloc(new_nbins * sizeof(*D->bins));

    for (idx = 0; idx < D->nbins; idx++) {
        while (D->bins[idx]) {
            struct list *cur = D->bins[idx];
            int new_idx = cur->hash % new_nbins;
            
            // remove node from old list;
            
            D->bins[idx] = cur->next;
            
            // insert node at fromt of new list
            
            cur->next = new_bins[new_idx];
            new_bins[new_idx] = cur;
        }
    }

    free(D->bins);
    D->bins = new_bins;
    D->nbins = new_nbins;

    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。