【问题标题】:Deleting element from linked list in C从C中的链表中删除元素
【发布时间】:2020-09-04 18:29:36
【问题描述】:

我正在尝试编写一个函数,该函数正在从我的链接列表中删除一个特定元素,但是当我到达该元素时它会因分段错误而崩溃。 这是我的代码的一部分

typedef struct dlist_t {
    int data;
    struct dlist_t *prev, *next;
} dlist_t;

typedef struct list_t {
    dlist_t *head, *tail;
} list_t;

int delElement(list_t *list, int elem) {
    while (list) {
        if ((list->head)->data == elem) {
            list->head->next = list->head->prev;
            list->head->prev = list->head->next;
            free(list);
            return 1;
        }
        list = list->head->next;
    }
    return 0;
}

【问题讨论】:

  • 看来代码没有意义。显示列表定义。
  • 用图表自己画出来。顺便说一句,这是不完整的代码。我们不知道结构是什么样子(尽管我们可能有一个好主意),我们不知道您如何分配您在此处释放的内存以及您如何填充链接列表。而且您可能对结构进行了类型定义(您不应该这样做,因为它没有任何帮助)。

标签: c struct linked-list doubly-linked-list function-definition


【解决方案1】:

您的函数定义没有意义。例如在这个赋值语句中

list = list->head->next;

赋值左侧(类型为list_t)和赋值右侧(类型为dlist_t)使用了不同类型的对象。

或者这个电话

free(list);

尝试释放列表而不是仅释放其一个节点。以此类推。

该函数可以如下所示,如下面的演示程序所示。

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

typedef struct dlist_t 
{
    int data;
    struct dlist_t *prev, *next;
} dlist_t;

typedef struct list_t 
{
    dlist_t *head, *tail;
} list_t;

int delElement( list_t* list, int elem )
{
    dlist_t **current = &list->head;

    while ( *current != NULL && ( *current )->data != elem )
    {
        current = &( *current )->next;
    }

    int success = *current != NULL;

    if ( success )
    {
        dlist_t *tmp = *current;

        if ( ( *current )->next != NULL )
        {
            ( *current )->next->prev  = ( *current )->prev;
        }
        else
        {
            list->tail = ( *current )->prev;
        }

        *current = ( *current )->next; 

        free( tmp );
    }

    return success;
}

int pushFront( list_t *list, int elem )
{
    dlist_t *new_node = malloc( sizeof( dlist_t ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->next = list->head;
        new_node->prev = NULL;
        new_node->data = elem;

        if ( list->head != NULL )
        {
            list->head->prev = new_node;
        }
        else
        {
            list->tail = new_node;
        }

        list->head = new_node;
    }

    return success;
}

int pushBack( list_t *list, int elem )
{
    dlist_t *new_node = malloc( sizeof( dlist_t ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->prev = list->tail;
        new_node->next = NULL;
        new_node->data = elem;

        if ( list->tail != NULL )
        {
            list->tail->next = new_node;
        }
        else
        {
            list->head = new_node;
        }

        list->tail = new_node;
    }

    return success;
}

void printList( list_t *list )
{
    for ( dlist_t *current = list->head; current != NULL; current = current->next )
    {
        printf( "%d -> ", current->data );
    }

    puts( "null" );
}


void printReverseList( list_t *list )
{
    for ( dlist_t *current = list->tail; current != NULL; current = current->prev )
    {
        printf( "%d -> ", current->data );
    }

    puts( "null" );
}

int main(void) 
{
    list_t list = { .head = NULL, .tail = NULL };

    const int N = 10;

    for ( int i = 0; i < N; i++ )
    {
        if ( i % 2 == 0 ) pushFront( &list, N / 2 - i / 2 - 1 );
        else pushBack( &list, N / 2 + i / 2 );
    }

    printList( &list );
    printReverseList( &list );

    putchar( '\n' );

    for ( size_t i = 0; i < N; i++ )
    {
        if ( i % 2 == 0 ) delElement( &list, i / 2 );
        else delElement( &list, N - i / 2 - 1 );

        printList( &list );
        printReverseList( &list );

        putchar( '\n' );
    }       

    return 0;
}

程序输出是

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null

2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null

2 -> 3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null

3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> null

3 -> 4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> 3 -> null

4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> null

4 -> 5 -> null
5 -> 4 -> null

5 -> null
5 -> null

null
null

玩这个程序并玩调查它。

不要忘记自己编写释放列表中所有已分配节点的函数。

【讨论】:

    【解决方案2】:

    我还不太确定是什么导致了您的崩溃,但这里我有一个应该可以工作的代码示例。 结构体定义:

    typedef int item_type;
    typedef struct _list* list;
    
    struct node {
    
        item_type data;
        struct node *next,*prev;
    
    };
    
    struct _list {
    
        struct node* head;
        struct node* tail;
        int size;
    };
    

    “元素”删除函数

    
    void list_del(list l,item_type data) {
    
        if (list->size ==0) {
            abort();
        }
    
        int i=0;
        struct node* head = l->head;
    
        while(i<list->size){
            if(head->data==data){
                head->prev = head->next;
                l->size -= 1;
                free(head);
                return;
            }else{
                head=head->next;
            }
        }
    
    }
    
    

    "item_type" 它是一个 typedef,如果你有很多函数并且你不应该太关心类型。在我们的示例中,如您所愿,输入 int

    【讨论】:

      【解决方案3】:

      别担心,试试这段代码。这是最简单的实现和删除链表中的节点,如果您遇到任何问题,请随时询问。

      #include <stdio.h>
      #include <stdlib.h>
      
      struct Node
      {
         int data;
         struct Node *next;
      }*first=NULL;
      
      void create(int A[],int n)
      {
         int i;
         struct Node *t,*last;
         first=(struct Node *)malloc(sizeof(struct Node));
         first->data=A[0];
         first->next=NULL;
         last=first;
      
       for(i=1;i<n;i++)
      
       {
         t=(struct Node*)malloc(sizeof(struct Node));
         t->data=A[i];
         t->next=NULL;
         last->next=t;
         last=t;
       }
      
      }
      
      void Display(struct Node *p)
      {
         while(p!=NULL)
         {
            printf("%d ",p->data);
            p=p->next;
         }
      }
      
      void RDisplay(struct Node *p)
      
      {
        if(p!=NULL)
        {
            RDisplay(p->next);
            printf("%d ",p->data);
      
        }
      }
      
      int Delete(struct Node *p,int index)
      {
         struct Node *q=NULL;
         int x=-1,i;
      
       if(index < 1 || index > count(p))
       return -1;
      
       if(index==1)
       {
          q=first;
          x=first->data;
          first=first->next;
          free(q);
          return x;
       }
      
       else
       {
         for(i=0;i<index-1;i++)
         {
             q=p;
             p=p->next;
         }
         q->next=p->next;
         x=p->data;
         free(p);
         return x;
      
       }
      
      
      }
      
      int main()
      {
      
          int A[]={10,20,30,40,50};
          create(A,5);
      
          printf(“%d\n",Delete(first),2);
          Display(first);
      
          return 0;
      }
      

      首先我们使用 malloc 函数创建了链表。我们已经创建了一个带有变量的结构,它将构建链表,即 "data" 并且还创建了 struct 类型的 pointer

      然后我们创建了一个函数名称“create”来创建我们的第一个节点。并根据它插入值。

      那么如你所见,我们g=已经使用for循环来加快创建链接列表的过程,直到n的值。

      然后为了显示链表,我们创建了函数名“Display” 如果 p!=NULL 即包含地址的节点最后一列,我们使用 for 循环打印该节点的值/数据。

      然后我们使用函数名“Delete”进行删除:

      第一步:我们是否需要一个指向第一个节点的指针“p”。

      第二步:现在首先移动到下一个节点。

      第三步:现在将已删除节点的值存储在新变量“x”中。

      第四步:删除p

      剩下的代码是使用两个指针从特定位置删除节点,一个指针代表前一个节点,下一个指针代表当前节点

      试试这个,或者用你的代码交叉检查你出错的地方。

      【讨论】:

      • 您的代码严重错误。它为其他读者树立了一个坏榜样,使其难以阅读。此外,您使用了非常不同的链表表示,因此代码与 OP 无关。在没有解释的情况下转储代码并没有真正的帮助。
      • 对此我感到非常抱歉,下次我将处理此问题时不会发生这种情况,我将对其进行编辑并尝试更清楚地发布它。
      • 我已经编辑了代码,如果您有疑问可以询问。
      • 很抱歉,您的代码仍然缩进不一致。例如在Delete 中,if 语句的缩进少于其前面的局部变量定义。 C 代码可能很棘手,已经有太多地方可以将错误隐藏在显而易见的地方,必须正确呈现才能使代码更易于发现软件缺陷的可读性。此外,您的简单链表不是 OP 所要求的:问题中的结构记录了一个带有 headtail 外壳的双向链表。更新比您的示例更复杂。
      猜你喜欢
      • 2021-03-26
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      相关资源
      最近更新 更多