c语言从链表任意位置删除元素
remove element from linked list at any position in c language
我有一个这样的链表:
1,jhon,19
2,萨拉,18
3,汤姆,20
4,杰克,22
我一直在尝试根据他们的 id 删除一个元素( 是第一个数字)。但为了做到这一点,我需要从任何位置删除这个元素。所以我想出了这段代码,我想知道它是否正确:
temp1=head;
if(head!=NULL && head->id==givenID) // if the element is in the first position
{
temp = head;
head = head->next;
free(temp);
}
else if(head!=NULL && head->id!=givenID){// search for the element in the middle
do{
temp2=head;
head = head->next;
}while(head->id !=givenID && head->next !=NULL);
if(head->next !=NULL && head->id==givenID){// if the element is in the middle
temp2->next=head->next;
free(head);
head=temp1;
}
else if(head->next ==NULL && head->id==givenID){// if the element is in the last position
temp->next=NULL;
free(head);
head=temp1;
}
}
谢谢
这段代码太复杂了,因为它有不必要的分支。您可以使用指向指针的指针来统一您的代码。
这个想法是将你的指针指向列表的 head
指针,然后指向列表初始元素的 next
指针,然后指向 next
列表第二个元素的指针,依此类推。这种方法的美妙之处在于,无论您在列表中的哪个位置,对指针的指针操作都保持不变!
代码如下所示:
// Point your pointer to pointer to the head of the list
struct node **pptr = &head;
while (*pptr != NULL) {
// Dereference pptr to get the pointer to current node
node *current = *pptr;
// Check if the id of this node matches what we're looking for
if (current->id == givenID) {
// Here is the "magic": assign the next pointer of the current node
// to whatever is pointed to by pptr.
// It could be a head, or a next of some node.
*pptr = current->next;
free(current);
break;
}
pptr = &(current->next);
}
就是这样!由于指向指针的指针不区分头节点和其他节点,因此没有进行额外的检查。
考虑使用哨兵节点。当您这样做时,所有特殊情况都会消失。
这是节点擦除在带哨兵的链表中的样子:
Iterator Erase( List* lst, Iterator here )
{
Iterator nxt = here->next;
Link( here->prev, here->next );
free( here );
lst->size -= 1;
return nxt;
}
Link并不比
复杂
void Link( Iterator n1, Iterator n2 )
{
n1->next = n2;
n2->prev = n1;
}
所有其他核心功能,如插入等同样微不足道。
我有一个这样的链表:
1,jhon,19
2,萨拉,18
3,汤姆,20
4,杰克,22
我一直在尝试根据他们的 id 删除一个元素( 是第一个数字)。但为了做到这一点,我需要从任何位置删除这个元素。所以我想出了这段代码,我想知道它是否正确:
temp1=head;
if(head!=NULL && head->id==givenID) // if the element is in the first position
{
temp = head;
head = head->next;
free(temp);
}
else if(head!=NULL && head->id!=givenID){// search for the element in the middle
do{
temp2=head;
head = head->next;
}while(head->id !=givenID && head->next !=NULL);
if(head->next !=NULL && head->id==givenID){// if the element is in the middle
temp2->next=head->next;
free(head);
head=temp1;
}
else if(head->next ==NULL && head->id==givenID){// if the element is in the last position
temp->next=NULL;
free(head);
head=temp1;
}
}
谢谢
这段代码太复杂了,因为它有不必要的分支。您可以使用指向指针的指针来统一您的代码。
这个想法是将你的指针指向列表的 head
指针,然后指向列表初始元素的 next
指针,然后指向 next
列表第二个元素的指针,依此类推。这种方法的美妙之处在于,无论您在列表中的哪个位置,对指针的指针操作都保持不变!
代码如下所示:
// Point your pointer to pointer to the head of the list
struct node **pptr = &head;
while (*pptr != NULL) {
// Dereference pptr to get the pointer to current node
node *current = *pptr;
// Check if the id of this node matches what we're looking for
if (current->id == givenID) {
// Here is the "magic": assign the next pointer of the current node
// to whatever is pointed to by pptr.
// It could be a head, or a next of some node.
*pptr = current->next;
free(current);
break;
}
pptr = &(current->next);
}
就是这样!由于指向指针的指针不区分头节点和其他节点,因此没有进行额外的检查。
考虑使用哨兵节点。当您这样做时,所有特殊情况都会消失。
这是节点擦除在带哨兵的链表中的样子:
Iterator Erase( List* lst, Iterator here )
{
Iterator nxt = here->next;
Link( here->prev, here->next );
free( here );
lst->size -= 1;
return nxt;
}
Link并不比
复杂void Link( Iterator n1, Iterator n2 )
{
n1->next = n2;
n2->prev = n1;
}
所有其他核心功能,如插入等同样微不足道。