【问题标题】:remove element from linked list at any position in c languagec语言从链表中任意位置删除元素
【发布时间】:2015-02-22 17:42:16
【问题描述】:

我有一个这样的链表:

1,jhon,19

2,萨拉,18

3,tom,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;
                }
              }

谢谢

【问题讨论】:

  • 我认为它适用于代码审查网站

标签: c list linked-list


【解决方案1】:

这段代码太复杂了,因为它有不必要的分支。您可以使用指向指针的指针来统一您的代码。

想法是将指针指向指向列表的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);
}

就是这样!由于指向指针的指针不区分头节点和其他节点,因此无需进行额外检查。

【讨论】:

    【解决方案2】:

    考虑使用哨兵节点。当您这样做时,所有特殊情况都会消失。
    这是节点擦除在带有哨兵的链表中的外观:

    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;
    }
    

    所有其他核心功能,如插入等。

    【讨论】:

      猜你喜欢
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 2020-09-04
      • 2021-03-26
      • 2020-10-29
      • 1970-01-01
      • 2010-10-17
      相关资源
      最近更新 更多