我需要使用C使用合并原则以递归方式从列表中删除重复项

时间:2013-01-16 19:33:55

标签: c recursion merge duplicate-removal

我试试这个:

    void
    remove_duplicate(List l, int p, int r){
        if(p<r){
            int q =(r+p)/2;
            remove_duplicate(l,p,q);
            remove_duplicate(l,q+1,r);
            merge_(l,p,q,r);
        }
    }

    void
    merge_(List lst, int p, int q, int r){
        int i = p;
        int j=q+1;
        int l = r;
        link lp = retNode(lst,p);
        link lq = retNode(lst,q+1);
        while(i<=q){
            j=q+1;
            while(j<=l){
                if(lp->item==lq->item){remNode(lst,j);j--;l--;}
                j++;lq=lq->next;}
                i++;lp = lp->next;}
    }

但是当我删除一个元素然后无效时,“子列表”的大小会降低吗?

1 个答案:

答案 0 :(得分:0)

这种递归方法不能很好地工作,因为当您从阵列中删除项目时发现,您必须将所有内容都移除。这会弄乱父级递归调用列表中的偏移量。

您可以修改对merge的调用,以便参数为指针,如果调整列表大小,它们将更新为新值。然后你还必须让remove_duplicates以同样的方式返回这些值。这可能非常繁琐,但是如果你改变列表的大小,那么我没有看到任何其他方法 - 递归链中的父调用需要知道它们的边界已经被内部调用删除了来自列表。只需记住在将它们传递给下一个调用之前,先获取指针传入的值的副本,否则你只需要指向同一个变量的指针,这将会破坏可怕的事情。

但是,你真的需要使用递归方法吗?我不认为这是最简单或最有效的方法 - 在这种情况下,迭代方法可能更容易实现。

您似乎正在使用链接列表,因此迭代方法可能如下所示:

void remove_duplicates(ListItem *items)
{
    while (items) {
        ListItem *current = items;
        while (current->next) {
            if (current->next->item == items->item) {
                current->next = current->next->next;
            } else {
                current = current->next;
            }
        }
        items = items->next;
    }
}

我假设您的列表在此示例中由NULL next指针终止,但它也应该很容易适应长度有限的列表。我还假设它只是单链接 - 双链表的基本方法是类似的,但当然你需要更新下一个和前一个指针。