【问题标题】:How to remove any node in a singly linked list如何删除单链表中的任何节点
【发布时间】:2011-03-25 14:42:28
【问题描述】:

这是我的代码:

#include<stdio.h>
#include<stdlib.h>

struct node
{ 
    int x;
    struct node *next;       
};

struct node *addNode(struct node *head, int y)
{
       struct node *traverser;
       traverser = head;
       if(traverser!=NULL)
       {                 
             while(traverser->next!=NULL)
             traverser=traverser->next;

             traverser -> next = malloc(sizeof(struct node));
             traverser -> next -> x = y;
             traverser -> next -> next = NULL;
       }
       else
       {
             head= malloc(sizeof(struct node));
             head -> x=y;
             head -> next = NULL;
       }    
       return head;
 }

 void display(struct node *head)
 {   
     struct node *traverser;
     traverser = head;

     while(traverser!=NULL)
     {
          printf("%d\n",traverser->x);
          traverser=traverser->next; 
     }
 }

 struct node *InitializeList(void)
 {
       return NULL;
 }

int main()
{
    struct node *head;
    head = InitializeList();
    head = addNode(head,2);
    head = addNode(head,15);
    head = addNode(head,5);
    head = addNode(head,8);
    display(head);  

    free(head);
    getchar();
}

我需要像这样删除 main 中的一个节点

struct node *head;
head = InitializeList();
head = addNode(head,2);
head = addNode(head,15);
head = addNode(head,5);
head = addNode(head,8);
display(head);  
removenode(5);
display(head);  
removenode(8); 
display(head);  
free(head);

在我的程序中删除特定节点时,这是我的 main() 代码。

但是我该怎么做呢? removenode() 只是函数名我应该使用什么算法?或者什么或如何删除它?

【问题讨论】:

  • 关于建议的副本:在删除第一个节点时,c# 在更新调用者的 head 副本方面是否存在相同的问题?可能stackoverflow.com/questions/1857457/… 是一个更好的副本,但那里的答案不完整。
  • @dmckee,无论您使用哪种语言,都必须移动头部。我认为这个问题与语言无关,因为他要求的是一种算法。与 C 的唯一真正区别是您必须确保在丢失指针之前释放节点。不管怎样,这个问题已经被问了无数次了。仅通过扫描“相关”侧边栏中的标题,就有 4 个候选重复项,专门处理从单链表中删除节点的问题,我相信如果我点击一下,我可以找到更多。我刚刚选择了第一个有不错答案的人。
  • @Karl:我只要求最好的副本,虽然您必须始终更新头部,但 c 的 use-pointers-for-pass-by-reference 语法以适合程序员习惯于具有真正的按引用传递语义的语言。以我的经验,这是学生在 c 中解决这个问题的最大障碍。

标签: c linked-list


【解决方案1】:

不是一个完整的答案,只是一些一般性的建议

为了弄清楚这种事情,通常只解决三种情况就足够了

  • 要移除的节点是head
  • 要移除的节点是尾部
  • 要删除的节点在列表内部

你会遇到的主要麻烦是

  • 确保任何先前节点中的“下一个”字段得到正确重置
  • 确保调用者获得或保留一个指向 new 头的 有效 指针。

请注意,有一个递归实现(想想n.next = remove(n.next,val))使这两个问题变得相同,并且您可以将其主要转换为循环以防止非常长的列表中的堆栈溢出。


可能出现的一个子问题是在列表中找到要删除的节点。通过将查找目标节点的部分与remove(node* head, node* target) 分开,您可以让您的生活更轻松吗?

【讨论】:

    【解决方案2】:

    我在 C 中写了一个关于链表的教程,也许它会有所帮助:

    http://www.4pmp.com/2009/10/linked-lists-in-c-push-pop-shift-and-unshift/

    【讨论】:

      【解决方案3】:

      算法原型需要是:

      struct node * removenode(struct node *head, int y);
      

      因为如果您要删除第一项,原来的“头”指针将不再有效。

      该算法只是简单地遍历列表,记住前一项(和头部),然后查找数据。找到后,将上一个项目的下一个指针设置为当前项目的下一个。

      【讨论】:

        【解决方案4】:

        概括地说,要删除任何节点,您需要做的是:

        1) 指向指向要删除的节点的项目。

        2) 将要删除的项目的引用设置为要删除的项目的下一个项目。

        3) 删除要删除的项目。

        这样,您的链被维护并且您已经从内存中释放了该元素。

        像这样:

        Head -> Item1 -> Item2 -> Item3 -> NULL
        

        如果你想删除Item2,你可以这样:

        Head -> Item1 -> Item2 -> Item3 -> NULL
                  ^       ^   (Grab pointers to these items)
        

        将 Item1 的 next 设置为 Item2 的 next,然后删除 Item2。

                   /--------------\
        Head -> Item1    Item2 -> Item3 -> NULL
                  ^       ^ (Delete 2)
        

        编辑:删除项目或项目 3:

        Head -> Item1 -> Item2 -> Item3 -> NULL
         ^       ^   (Grab pointers to these items)
        

        将head重新指向Item2,然后删除Item1:

           /--------------\
        Head    Item1 -> Item2 -> Item3 -> NULL
         ^       ^ (Delete 1)
        

        或

        Head -> Item1 -> Item2 -> Item3 -> NULL
                            ^       ^   (Grab pointers to these items)
        

        将head重新指向Item2,然后删除Item1:

                            /--------------\
        Head -> Item1 -> Item2   Item3 -> NULL
                           ^       ^ (Delete 3)
        

        【讨论】:

        • 该算法适用于删除 Item1 和 Item3。但是,我将在我的答案中显示相同的集合。
        • 很明显它适用于尾部(几乎所有方法都免费提供),但您通常需要证明您已经解决了删除头部的更新问题。见unwind's answer。
        【解决方案5】:

        看看这是否适合你,也许是存储在我的电脑中的某个地方,用于这样的情况:

        void RemoveNode(struct node*x)
        {
            struct node *temp=x,*tempo=NULL;
            int i=0,n;
            printf("\nWould you like to delete a node?\nPress 1 for Yes 2 for No: ");
            scanf("%d",&i);
            if(i==1)
            {
                printf("Enter nth node to be deleted");
                scanf("%d",&n);
                i=0;
                if(n==1)
                {
                x=temp->next;
                free(temp);
                }
                while(i<n-2)
                {
                temp=temp->next;
                i++;
                }
                if(temp->next->next==NULL)
                {
                tempo=temp->next;
                temp->next=NULL;
                free(tempo);
                }
                else
                {
                tempo=temp->next;
                temp->next=temp->next->next;
                free(tempo);
                }
            }
            else
            printf("\n No Changes Made\nExiting....");
        }
        

        始终重要的是头部。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多