【问题标题】:How to delete multiple occurrences of multiple variables in a linked list in c如何在c中删除链表中多次出现的多个变量
【发布时间】:2020-05-31 07:18:21
【问题描述】:

我是c编程的初学者,我已经尝试了几天来解决以下问题:

如何删除在以下列表中出现至少 3 次的数字:

3→3→1→2→4→3→5→3→5→4

结果:

1→2→4→5→5→4。

现在我知道如何删除链表中多次出现的“one”键,例如删除链表中出现的所有“1”,但似乎无法理解如何删除多次出现的多个变量.这简直要了我的命。如果有人可以提供帮助,我将不胜感激。提前致谢。

【问题讨论】:

  • 对列表进行多次遍历。例如,一种用于计算所有出现次数,另一种用于删除节点。
  • 所以我想这是一个处理链表的练习——扫描和删除项目等等。简单的方法,它对每个键值进行扫描(两次扫描恰好出现两次的键值)。但那是 O(n^2) - 啊。要解决这个问题,您需要一些数据结构来收集一次扫描的所有键并识别要删除的键。然后在第二次扫描中执行所有删除操作。 (要获得额外的功劳,请在一次扫描中完成所有操作。)当然,如果您的列表保证“简短”:保持简单。

标签: c memory-management struct linked-list singly-linked-list


【解决方案1】:

似乎没有人急于帮助你。:)

如果通过引用将指针头传递给函数,则编写函数更简单。

这是一个演示程序,展示了如何实现该功能。

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

struct Node
{
    int data;
    struct Node *next;
};

int insert( struct Node **head, int data )
{
    struct Node *node = malloc( sizeof( struct Node ) );
    int success = node != NULL;

    if ( success )
    {
        node->data = data;
        node->next = *head;
        *head = node;
    }

    return success;
}

void out( struct Node *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d -> ", head->data );
    }
    puts( "null" );
}

void remove_repetitive( struct Node **head )
{
    const size_t LIMIT = 3;

    while ( *head != NULL )
    {
        size_t count = 1;

        int data = ( *head )->data;

        for ( struct Node *node = ( *head )->next; 
              count < LIMIT && node != NULL; node = node->next )
        {
            if ( node->data == data ) ++count;
        }

        if ( count == LIMIT )
        {
            for ( struct Node **node = head; *node != NULL; )
            {
                if ( ( *node )->data == data )
                {
                    struct Node *tmp = *node;
                    *node = ( *node )->next;
                    free( tmp );
                }
                else
                {
                    node = &( *node )->next;
                }
            }
        }
        else
        {
            head = &( *head )->next;
        }
    }
}

int main(void) 
{
    struct Node *head = NULL;
    int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };

    const size_t N = sizeof( a ) / sizeof( *a );

    for ( size_t i = 0; i < N; i++ )
    {
        insert( &head, a[i] );
    }

    out( head );

    remove_repetitive( &head );

    out( head );

    return 0;
}

程序输出是

3 -> 3 -> 1 -> 2 -> 4 -> 3 -> 5 -> 3 -> 5 -> 4 -> null
1 -> 2 -> 4 -> 5 -> 5 -> 4 -> null

函数remove_repetitive可以拆分成两个函数,如下所示。

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

struct Node
{
    int data;
    struct Node *next;
};

int insert( struct Node **head, int data )
{
    struct Node *node = malloc( sizeof( struct Node ) );
    int success = node != NULL;

    if ( success )
    {
        node->data = data;
        node->next = *head;
        *head = node;
    }

    return success;
}

void out( struct Node *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d -> ", head->data );
    }
    puts( "null" );
}

void remove_all( struct Node **head, int data )
{
    while ( *head != NULL )
    {
        if ( ( *head )->data == data )
        {
            struct Node *tmp = *head;
            *head = ( *head )->next;
            free( tmp );
        }
        else
        {
            head = &( *head )->next;
        }
    }
}

void remove_repetitive( struct Node **head )
{
    const size_t LIMIT = 3;

    while ( *head != NULL )
    {
        size_t count = 1;

        int data = ( *head )->data;

        for ( struct Node *node = ( *head )->next; 
              count < LIMIT && node != NULL; node = node->next )
        {
            if ( node->data == data ) ++count;
        }

        if ( count == LIMIT )
        {
            remove_all( head, data );   
        }
        else
        {
            head = &( *head )->next;
        }
    }
}

int main(void) 
{
    struct Node *head = NULL;
    int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };

    const size_t N = sizeof( a ) / sizeof( *a );

    for ( size_t i = 0; i < N; i++ )
    {
        insert( &head, a[i] );
    }

    out( head );

    remove_repetitive( &head );

    out( head );

    return 0;
}

程序输出同上图。

【讨论】:

  • 代码中的逻辑删除可被“3”整除的数字,但问题是“删除元素,即出现次数 >= 3。”
  • 是的,这是我的问题,在删除出现 >= 3 次的不同变量的过程中,我总是忘记了头部。最后,该函数必须将更改后的列表的头部返回给调用者。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 2013-11-24
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多