簡體   English   中英

將指向C中的鏈表的數組加倍

[英]Doubling an array that points to a linked list in C

我正在用C實現哈希集,其中我的數組指向一個鏈表

這是鏈接列表:

typedef struct hashnode hashnode;

struct hashnode {
    char *word;
    // will hold our word as a string

    hashnode *link;
    //will be used only if chaining
};

這是哈希集:

struct hashset {
    size_t size;
    //size of entire array

    size_t load;
    //number of words total

    hashnode **chains;
    //linked list (if words have same index);
};

現在我的雙數組代碼有問題,我相信這里的代碼有一個懸空指針:

void dbl_array(hashset *this) {
    size_t newlen = this->size +1;
    newlen *= 2;
    //double siz
    hashnode **new_array = malloc(newlen * sizeof(hashnode*));
    //new array
    int array_end = (int)this->size;//load;
    //end of old array
    for(int i = 0; i < array_end; i++) {
        //loop through old
        int index = i;
        if(this->chains[index] == NULL) {
            continue;
        }
        else {
            hashnode *nod;
            int i=0;
            for(nod = this->chains[index]; nod != NULL; nod = nod->link) {
                if(nod == NULL) 
                    return;
                size_t tmp = strhash(nod->word) % newlen;
                //compute hash
                hashnode *newnod;
                newnod = malloc(sizeof(hashnode*));
                newnod->word = strdup(nod->word);
                newnod->link = NULL;
                if(new_array[tmp] == NULL) { 
                    //if new array does not already have a word at index
                    new_array[tmp] = newnod;
                }
                else {
                    //if word is here then link to old one
                    newnod->link = new_array[tmp];
                    new_array[tmp] = newnod;
                }
                printf("newarray has: %s @ {%d} \n", new_array[tmp]->word, tmp);
                //testing insertion
                i++;
            }
            free(nod);
        }
    }
    this->chains = new_array;
    this->size = newlen;
    free(new_array);
    printf("new size %d\n", this->size);
}

因此,在運行GDB之后,我發現添加新節點時出了點問題

完全沒有理由為哈希表擴展分配新的沖突節點。 擴展哈希表的算法相對簡單:

  1. 計算新表的大小
  2. 分配新表
  3. 枚舉舊表中的所有鏈
    1. 對於每個鏈,枚舉所有節點
      1. 對於每個節點,根據新表大小計算新哈希
      2. 將節點移動到新表中的適當插槽

完成上述操作后,您也是如此。 只需將新表連接到hashset ,並確保將大小成員更新為新大小。 舊表被丟棄。

以下代碼假定您在加倍之前已正確管理了哈希表。 接着就,隨即:

  • 所有未使用的表插槽均正確為NULL
  • 所有沖突列表均以NULL終止。

如果您不能同時保證這兩個條件,則將哈希表的大小加倍是您最少的擔心。

void hashset_expand(hashset* hs)
{
    size_t new_size = 2 * (1 + hs->size), i, idx;
    hash node *next, *nod, **tbl = calloc(new_size, sizeof(*tbl));

    // walk old table, and each chain within it.
    for (i=0; i<hs->size; ++i)
    {
        next = hs->chains[i];
        while (next)
        {
            nod = next;
            next = next->link; // must be done **before** relink
            idx = strhash(nod->word) % new_size;
            nod->link = tbl[idx];
            tbl[idx] = nod;
        }
    }

    // finish up, deleting the old bed.
    free(hs->chains);
    hs->chains = tbl;
    hs->size = new_size;
}

這就是全部。 不要比這更復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM