CS50拼写:卸载执行80,000,000次以上释放

时间:2019-04-30 20:14:18

标签: c cs50

这是哈佛大学CS50中的pset 5。它主要包括加载字典,检查是否在加载的字典中找到了所选文本中的每个单词,然后卸载(释放所有分配的内存)。 所有其他功能都起作用,但是如所述,它仅执行80,000,000次以上的释放,而在程序中只有143,094个malloc,我是一个新手,所以这对我来说是个不可思议的事情。以下是卸载的相关功能。

编辑(1):以下是有关变量 hashtable 的上下文。

typedef struct node
{
    char word[LENGTH+2];
    struct node *next;
}
node;

node *hashtable[264636] = { NULL };

我将每个元素初始化为NULL,以便在卸载时可以轻松跳过哈希函数中未生成键的索引值。

//LOAD FUNCTION: Loads the dictionary into a hash table. Djb2 function used. 

bool load(const char *dictionary)
{
    head = malloc(sizeof(node));
    head->next = NULL;
    if (head == NULL)
    {
        unload();
        return false;
    }
    opntr = fopen(dictionary, "r");

    while (fscanf(opntr, "%s", WORD) != EOF)
    {
        wnode = malloc(sizeof(node));
        if (wnode == NULL)
        {
            unload();
            return false;
        }
        strcpy(wnode->word, WORD);
        wnode->next = head; 
        head = wnode; 
        unsigned long key = hash(wnode->word);
        hashtable[key] = wnode;
        wnode = wnode->next;
    }
    return true;
}
// Checks whether the input word is somewhere within the dictionary

bool check(const char *word)
{
    char dword[strlen(word) + 1];
    strcpy(dword, word);
    for (int c = 0; c < strlen(dword); c++)
    {
        dword[c] = tolower(dword[c]);
    }
    int key_w;
    key_w = hash(dword);
    node *cursor = hashtable[key_w];
    while (cursor != NULL)
    {
        if (strcmp(cursor->word, dword) == 0)
        {
            return true;
        }
        cursor = cursor->next; 
    }
    return false;
}

// Unloads memory allocated (?) to store the dictionary

bool unload(void)
{
    for (int in = 0; in < 264636; in++)
    {
        node *fhead = hashtable[in];             
        while (fhead != NULL)
        {
            node *fcursor = fhead->next;
            free(fhead);
            fhead = fcursor;
        }
    }
    return true;
}

1 个答案:

答案 0 :(得分:0)

如果有人发现有帮助,则问题出在加载功能之内。分配的节点错误地更新,以使哈希表数组的元素不是独立的链表,并且每次我们想要添加节点时,我都不必要使用头节点指向列表的第一个元素。相反,要向哈希表数组中的相应元素添加新节点,我们将元素本身用作链接列表的头部,并对其进行排列,使其指向添加的每个节点,从而成功跟踪节点的开头。链表。哈希表中的每个元素最初都指向NULL,以便我们可以找到每个链表的结尾。

int null()
{
    for (int i = 0; i < 264636; i++)
    {
        hashtable[i]->next = NULL;
    }
    return 0;
}

bool load(const char *dictionary)
{

    opntr = fopen(dictionary, "r");
    while (fscanf(opntr, "%s", WORD) != EOF)
    {
        wnode = malloc(sizeof(node));
        if (wnode == NULL)
        {
            unload();
            return false;
        }
        strcpy(wnode->word, WORD);
        unsigned long key = hash(wnode->word);
        wnode->next = hashtable[key]; 
        hashtable[key] = wnode; 
    }
    return true;
}