C 在链表中保留所有数字的一个匹配项

C 在链表中保留所有数字的一个匹配项,c,recursion,linked-list,C,Recursion,Linked List,我想找到一种算法,使用递归在链表中保持每个数字只出现一次 ,我知道递归根本不是解决这个问题的好选择,但我想尝试一下 如需更多校准: input : 1->2->1->3->3->2->1->4 output : 1->2->3->4 这是我制作的一个程序,使用递归只保留给定数字的一次出现,但我无法开发它来解决整个问题。我能得到一些帮助吗?提前谢谢 list* wipe(list* head,int val) { if(hea

我想找到一种算法,使用递归在链表中保持每个数字只出现一次 ,我知道递归根本不是解决这个问题的好选择,但我想尝试一下

如需更多校准:

input : 1->2->1->3->3->2->1->4

output : 1->2->3->4
这是我制作的一个程序,使用递归只保留给定数字的一次出现,但我无法开发它来解决整个问题。我能得到一些帮助吗?提前谢谢

list* wipe(list* head,int val)
{
    if(head==NULL)  return head;
    static int occ=1;
    if(head->data == val)
    {
        if(occ-- < 1)
        {
            list* temp=head;
            head=head->next;
            free(temp);
            return wipe(head,val);
        }
    }
    head->next=wipe(head->next,val);
    return head;
}
list*擦除(list*head,int val)
{
如果(head==NULL)返回head;
静态int occ=1;
如果(头部->数据==val)
{
如果(occ--<1)
{
列表*温度=头部;
头部=头部->下一步;
免费(临时);
返回擦拭(头部,val);
}
}
头部->下一步=擦拭(头部->下一步,val);
回流头;
}
occ仅在您执行函数时设置为1,因此从第二次
(head->data==val)
为真,无论测试
(occ--<1)
为真,这不是正确的方法

您可以执行类似操作,将列表修改为仅包含唯一编号:

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

typedef struct List {
  struct List * next;
  int data;
} List;

/* remove from l all the cells having data equals to v */
List * wipe(int v, List * l)
{
  if (l == NULL)
    return l;
  else if (l->data != v) {
    l->next = wipe(v, l->next);
    return l;
  }
  else {
    List * n = l->next;
    
    free(l);
    return wipe(v, n);
  }
}

/* modify the argument to not have duplicated numbers */
void simplify(List * l)
{
  while (l != NULL) {
    l->next = wipe(l->data, l->next);
    l = l->next;
  }
}

/* helper function to construct a list */
List * mk(int v, List * n) {
  List * l = malloc(sizeof(*l));
  
  l->data = v;
  l->next = n;
  return l;
}

/* print the list */
void pr(List * l)
{
  while (l != NULL) {
    printf("%d ", l->data);
    l = l->next;
  }
  putchar('\n');
}


int main()
{
  List * l = mk(1, mk(2, mk(1, mk(3, mk(3, mk(2, mk(1, mk(4, NULL))))))));
  
  pr(l);
  simplify(l);
  pr(l);
  
  /* free the rest of the list */
  while (l) {
    List * n = l->next;
    
    free(l);
    l = n;
  }
  
  return 0;
}
这样就有了O(n2)的复杂性


一种更快的方法是首先对列表中的元素进行排序,然后删除重复的元素,从而允许具有排序的复杂性,因此可能是O(n*log(n))(可能使用临时数组进行排序)

如果我理解正确,您需要一个递归函数,该函数仅在列表中没有数字时才将数字附加到列表中

如果是这样的话,那么递归函数可以如下所示

int append( list **head, int val )
{
    if ( *head == NULL )
    {
        *head = malloc( sizeof( **head ) );
        int success = *head != NULL;

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

        return success;
    }
    else if ( ( *head )->data != val )
    {
        return append( &( *head )->next, val );
    }
    else
    {
        return 0;
    }
} 
append( &head, val );
如果你有这样的声明

list *head = NULL;
然后可以调用该函数,例如

int append( list **head, int val )
{
    if ( *head == NULL )
    {
        *head = malloc( sizeof( **head ) );
        int success = *head != NULL;

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

        return success;
    }
    else if ( ( *head )->data != val )
    {
        return append( &( *head )->next, val );
    }
    else
    {
        return 0;
    }
} 
append( &head, val );
或者

if ( append( &head, val ) )
{
    printf( "The value %d is appended to the list.\n", val );
}  

遍历并执行某种修改的插入排序,以将数字插入到新的链表中。修改为t不会插入重复的数字。@学习者整个问题是什么?occ仅在您执行该函数时设置为1,因此从第二次开始
(head->data==val)
无论测试值
(occ--<1)
将为真=>无法work@VladfromMoscow整个问题是保持所有数字只出现一次,我只找到了保持一个给定数字出现一次的解决方案,我想对链接列表中的所有数字做同样的处理。解决方案很简单,请参见答案