C 如果同一索引中的下一个节点不为空,如何删除单链链表哈希表的第一个节点?

C 如果同一索引中的下一个节点不为空,如何删除单链链表哈希表的第一个节点?,c,hashtable,C,Hashtable,这是我的功能,如果我使用此功能删除第一个节点,它将删除所有剩余的节点->下一个节点,有人可以帮助我吗 struct node* popCH(char ex[]){ int hash_index = Hash(ex); node* temp = head[hash_index]; if(temp==NULL){ return NULL; } while(temp->next!=NULL && strc

这是我的功能,如果我使用此功能删除第一个节点,它将删除所有剩余的节点->下一个节点,有人可以帮助我吗

struct node* popCH(char ex[]){
    int hash_index = Hash(ex);
    node* temp = head[hash_index];
    
    if(temp==NULL){
        return NULL;
    }
    
    while(temp->next!=NULL && strcmp(temp->next->ex,ex)!=0){
            temp=temp->next;
        }

    if(temp->next==NULL && strcmp(temp->ex,ex)==0){
        free(temp);
        temp=NULL;
        head[hash_index]=NULL;
    }
    
    else if(temp->next!=NULL && strcmp(temp->ex,ex)==0){
        node* temp2 = temp;
        temp = temp->next;
        temp = head[hash_index]->next;
        free(temp2);
        temp2=NULL;
    }
}

应该使用指向节点指针的指针,以便可以删除该节点,并将指向该节点的指针更新为指向下一个节点,而不管该指针是节点中指针的头指针

struct data* popCH(char ex[]){
    int hash_index = Hash(ex);
    node** temp = &head[hash_index];
    
    if(*temp==NULL){
        return NULL;
    }
    
    while(*temp!=NULL && strcmp((*temp)->ex,ex)!=0){
        temp=&(*temp)->next;
    }

    if(*temp!=NULL){
        node *temp2 = (*temp)->next;
        free(*temp);
        *temp=temp2;
    }

    /* return something not to let caller invoke undefined behavior by using the return value */
    return NULL;
}

应该使用指向节点指针的指针,以便可以删除该节点,并将指向该节点的指针更新为指向下一个节点,而不管该指针是节点中指针的头指针

struct data* popCH(char ex[]){
    int hash_index = Hash(ex);
    node** temp = &head[hash_index];
    
    if(*temp==NULL){
        return NULL;
    }
    
    while(*temp!=NULL && strcmp((*temp)->ex,ex)!=0){
        temp=&(*temp)->next;
    }

    if(*temp!=NULL){
        node *temp2 = (*temp)->next;
        free(*temp);
        *temp=temp2;
    }

    /* return something not to let caller invoke undefined behavior by using the return value */
    return NULL;
}

一种方法是使用指向指针的指针,这已经包含在一个优秀的答案中

另一种方法是跟踪指向前一个节点的指针,当没有前一个节点时,该指针为空:

node *prev = NULL;

while (temp != NULL && strcmp(temp->ex, ex) != 0) {
   prev = temp;
   temp = temp->next;
}

if (temp != NULL) { // found matching node
   // retain data pointer to return before freeing
   struct data *data = temp->data;

   // two deletion cases: middle of chain or front
   if (prev)
     prev->next = temp->next;
   else
     head[hash_index] = temp->next;

   free(temp);
   return data;
}

// not found
return NULL;
如果给链一个代理父对象,我们可以避免出现两种删除情况。也就是说,我们在列表的前面添加一个虚拟节点,作为第一个节点的前一个节点:

struct data* popCH(const char *ex){
    int hash_index = Hash(ex);
    // transfer chain into fake extra previous node:
    struct node parent = { .next = head[hash_index] };
    node *prev = &parent;
    node *temp = prev->next;
    

    while (temp != NULL && strcmp(temp->ex, ex) != 0) {
       prev = temp;
       temp = temp->next;
    }

    if (temp != NULL) { // found matching node
       // retain data pointer to return before freeing
       struct data *data = temp->data;

       // splice temp out of list by getting
       // the previous node to skip it
       prev->next = temp->next;

       // transfer updated chain back into table:
       head[hash_index] = parent.next;

       free(temp);
       return data;
    }

    // not found
    return NULL;
}
我们已经从代码中删除了一些测试,但是还有一些不必要的内存写入。在返回之前,我们将分配给
head[hash_index]
是否确实需要这样做;只有父级的
是必需的。下一个
已更改。此外,我们已经分配了一个完整的
节点
局部变量并初始化了它的所有字段,即使我们只访问`。我们可以通过避免使用初始值设定项来避免这样做:

    int hash_index = Hash(ex);
    // transfer chain into fake extra previous node:
    struct node parent;
    node *prev = &parent;
    node *temp = head[hash_index];

    // initialize just parent.next member by assignment;
    // other members are left uninitialized.
    parent.next = temp;

    // rest of code ...

一种方法是使用指向指针的指针,这已经包含在一个优秀的答案中

另一种方法是跟踪指向前一个节点的指针,当没有前一个节点时,该指针为空:

node *prev = NULL;

while (temp != NULL && strcmp(temp->ex, ex) != 0) {
   prev = temp;
   temp = temp->next;
}

if (temp != NULL) { // found matching node
   // retain data pointer to return before freeing
   struct data *data = temp->data;

   // two deletion cases: middle of chain or front
   if (prev)
     prev->next = temp->next;
   else
     head[hash_index] = temp->next;

   free(temp);
   return data;
}

// not found
return NULL;
如果给链一个代理父对象,我们可以避免出现两种删除情况。也就是说,我们在列表的前面添加一个虚拟节点,作为第一个节点的前一个节点:

struct data* popCH(const char *ex){
    int hash_index = Hash(ex);
    // transfer chain into fake extra previous node:
    struct node parent = { .next = head[hash_index] };
    node *prev = &parent;
    node *temp = prev->next;
    

    while (temp != NULL && strcmp(temp->ex, ex) != 0) {
       prev = temp;
       temp = temp->next;
    }

    if (temp != NULL) { // found matching node
       // retain data pointer to return before freeing
       struct data *data = temp->data;

       // splice temp out of list by getting
       // the previous node to skip it
       prev->next = temp->next;

       // transfer updated chain back into table:
       head[hash_index] = parent.next;

       free(temp);
       return data;
    }

    // not found
    return NULL;
}
我们已经从代码中删除了一些测试,但是还有一些不必要的内存写入。在返回之前,我们将分配给
head[hash_index]
是否确实需要这样做;只有父级的
是必需的。下一个
已更改。此外,我们已经分配了一个完整的
节点
局部变量并初始化了它的所有字段,即使我们只访问`。我们可以通过避免使用初始值设定项来避免这样做:

    int hash_index = Hash(ex);
    // transfer chain into fake extra previous node:
    struct node parent;
    node *prev = &parent;
    node *temp = head[hash_index];

    // initialize just parent.next member by assignment;
    // other members are left uninitialized.
    parent.next = temp;

    // rest of code ...

它向我显示错误消息“data::data”在这行代码中的使用无效struct data*data=temp->data@奥利:那是因为我在猜测你的数据结构。在您的问题中,您定义了函数,使其返回
struct data*
,但在任何地方都没有
return
语句。我猜测,当我们
popCH
哈希表时,我们应该在成功的情况下返回数据,在未找到的情况下,返回
NULL
。然后,我对
数据的位置进行了最简单的猜测;你必须根据实际情况自己解决这个问题。
data::data
,顺便问一下?这是不是C++?它告诉我错误信息:在这个代码行中使用“数据::数据”结构数据*数据= TEMP->数据;@奥利:那是因为我在猜测你的数据结构。在您的问题中,您定义了函数,使其返回
struct data*
,但在任何地方都没有
return
语句。我猜测,当我们
popCH
哈希表时,我们应该在成功的情况下返回数据,在未找到的情况下,返回
NULL
。然后,我对
数据的位置进行了最简单的猜测;你必须根据实际情况自己解决这个问题。
data::data
,顺便问一下?这是C++吗?