从链接列表中删除元素

时间:2020-07-08 18:39:44

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

假设我在下面有此列表:

List of CDData
    1: Test1
    2: Test2
    3: Test3
    4: Test4
    5: Test5
    6: Test6

现在我想使用链接列表从列表中删除第三个: free(removeFromDList(3)); 这是我的功能:

TCD *removeFromDList(int res)
{
    int count = 0;
    TCD *CDData = First;
    CDData->Prev = First;

    if (First == NULL)
    {
        printf("Error\n");
        return NULL;
    }

    while (CDData)
    {
        count++;
        if (count == res)
        {
            if (count == 1)
            {
                if (CDData == Last)
                    Last = NULL;
                First = First->Next;
                return CDData;
            }
            else
            {
                while (CDData != NULL)
                {
                    CDData->Prev = CDData->Next;
                    if (CDData == Last)
                        Last = CDData->Prev;

                    // printf("%s",CDData->Title) I tested here whether my function is going to 
                    //  delete the third one or not with the printf() and it's actually printing the third one 
                    // Which means it's correct 
                   
                    return CDData;
                }
            }
        }

        else
            CDData->Prev = CDData;
        CDData = CDData->Next;
    }
}

顺便说一下,这是TCD的定义

typedef struct F
{
 char *Title;
 struct F *Next;
 struct F *Prev;
}TCD;

现在,在重新打印我的列表之后,似乎所有CDData(整个Data结构)都已释放。有什么想法吗?

我将其作为输出

List of CDData

 
 
  
   

1 个答案:

答案 0 :(得分:1)

我认为在这个结构定义中

typedef struct F
{
 char *Titel;
 struct F *Next;
 struct F *Prev;
}TCD;

您的意思是第一个数据成员的名称是Title,而不是Titel

您需要为该数据成员指向的字符串动态分配内存。

您的函数至少可以调用未定义的行为,因为起初,全局变量First(当函数依赖于全局变量时是个坏主意)可以等于NULL。因此,在此代码段中

TCD *CDData = First;
CDData->Prev = First;

尝试使用空指针(CDData->Prev)访问内存。

此内部while循环

            while (CDData != NULL)
            {
                CDData->Prev = CDData->Next;
                if (CDData == Last)
                    Last = CDData->Prev;

                // printf("%s",CDData->Title) I tested here whether my function is going to 
                //  delete the third one or not with the printf() and it's actually printing the third one 
                // Which means it's correct 
               
                return CDData;
            }

没有道理。

请注意,C索引中的数字从0开始。

使用您的方法,可以按照以下演示程序中所示的方式编写函数。

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

typedef struct F
{
    char *Title;
    struct F *Next;
    struct F *Prev;
} TCD;

TCD *First, *Last;

TCD * removeFromDList( size_t n )
{
    TCD **Current = &First;
    
    while ( *Current && n--)
    {
        Current = &( *Current )->Next;
    }
    
    TCD *target = *Current;
    
    if ( *Current )
    {
        if ( ( *Current )->Next == NULL ) 
        {
            Last = ( *Current )->Prev;  
        }
        else
        {
            ( *Current )->Next->Prev = ( *Current )->Prev;
        }
        
        *Current = ( *Current )->Next;
    }
    
    return target;
}

int append( const char *s )
{
    TCD *Current = malloc( sizeof( TCD ) );
    int success = Current != NULL;
    
    if ( success )
    {
        Current->Title = malloc( strlen( s ) + 1 );
        success = Current->Title != NULL;
        
        if ( success )
        {
            strcpy( Current->Title, s );
            Current->Prev = Last;
            Current->Next = NULL;
        }
        else
        {
            free( Current );
        }
    }
    
    if ( success )
    {
        if ( Last )
        {
            Last = Last->Next = Current;
        }
        else
        {
            First = Last = Current;
        }
    }
    
    return success;
}

FILE * display( FILE *fp )
{
    for ( TCD *Current = First; Current; Current = Current->Next )
    {
        fprintf( fp, "%s -> ", Current->Title );
    }
    
    fputs( "NULL", fp );
    
    return fp;
}

int main(void) 
{
    
    for ( char s[] = "A"; s[0] != 'E'; ++*s )
    {
        append( s );
    }
    
    
    fputc( '\n', display( stdout ) );
    
    TCD *p = removeFromDList( 3 );
    free( p->Title );
    free( p );
    fputc( '\n', display( stdout ) );
    
    p = removeFromDList( 1 );
    free( p->Title );
    free( p );
    fputc( '\n', display( stdout ) );
    
    p = removeFromDList( 0 );
    free( p->Title );
    free( p );
    fputc( '\n', display( stdout ) );
    
    p = removeFromDList( 0 );
    free( p->Title );
    free( p );
    fputc( '\n', display( stdout ) );
    
    printf( "First == NULL : %d, Last == NULL : %d\n", First == NULL, Last == NULL );
    return 0;
}

程序输出为

A -> B -> C -> D -> NULL
A -> B -> C -> NULL
A -> C -> NULL
C -> NULL
NULL
First == NULL : 1, Last == NULL : 1