this is my funtion, if i use this function to delete the first node it will delete all the rest of node->next node, anyone can help me?
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;
}
}
You should use a pointer to a pointer to a node so that the node can be deleted and the pointer to the node is updated to point at the next node regardless of the pointer is the head pointer of a pointer in a node.
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;
}
One approach is with a pointer-to-pointer, which is already covered by an excellent answer.
Another one is simply to keep track of the pointer to the previous node, which is null when there is no previous node:
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;
We can avoid having two deletion cases if we give the chain a surrogate parent. That is to say, we add a dummy node to the front of the list which serves as the previous node for the first node:
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;
}
We have eliminated some tests from the code, but there are some unnecessary memory writes. Before returning, we assign to head[hash_index]
whether or not that is actually necessary; it is only necessary of parent.next
has changed. Moreover, we have allocated an entire node
local variable and initialized all of its fields, even though we only ever access `. We can avoid doing that by avoiding the initializer:
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 ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.