【问题标题】:linked list with no duplicates没有重复的链表
【发布时间】:2009-09-01 19:15:31
【问题描述】:

我有以下代码(对于我的简单测试是正确的)用于没有重复的链表,但我认为它有点难看。

谁能推荐一种更简洁的方法来处理重复代码? 当前有问题的是:

if( (val == cur->val) || (cur->next && (val == cur->next->val)) )

但我认为使用不同的比较运算符可能存在更好的解决方案(我没有看到)。

另外,有人可以给我一个“有用的”断言的建议或在这里。很难判断何时断言,特别是如果你有一个 if 语句为你做这件事。

struct Node 
{
    Node(int v):val(v),next(NULL){}
    int val;
    Node * next;
};

void insert(Node ** ppHead, const int val)
{
    if(ppHead == NULL)
        return;
    if(*ppHead == NULL || val < (*ppHead)->val)
    {
        Node * tmp = new Node(val); // new throws
        tmp->next = *ppHead;
        *ppHead = tmp;
    }
    else
    {
        Node * cur = *ppHead;
        while(cur->next && (val > cur->next->val))
            cur = cur->next;

        if( (val == cur->val) || (cur->next && (val == cur->next->val)) )
            return;

        Node * tmp = new Node(val); // new throws
        tmp->next = cur->next;
        cur->next = tmp;
    }
    return;
}


int _tmain(int argc, _TCHAR* argv[])
{
    Node * list = NULL;
    int x[] = { 5, 4, 6, 7, 1, 8, 1, 8, 7, 2, 3, 0, 1, 0, 4, 9, 9 };
    int size = sizeof(x) / sizeof(x[0]);
    for(int i = 0; i < size; i++)
        insert(&list, x[i]);
    Node * cur = list;
    while(cur) {
        printf (" %d", cur->val);
        cur = cur->next;
    }
    printf("\n");
    return 0;
}

【问题讨论】:

  • 也许您在作业中使用了错误的数据结构。例如,您是否需要按特定顺序存储节点?如果没有,使用哈希表或平衡二叉树重写代码非常容易。
  • 谢谢朱丽叶,但这是一个编码能力问题。 ;-) 不是我遇到的真正问题。

标签: c++ data-structures linked-list


【解决方案1】:

我会这样写:

void insert(Node ** ppHead, const int val)
{
    if (ppHead == NULL)
        return;
    while (*ppHead && (*ppHead)->val < val)
        ppHead = &(*ppHead)->next;
    if (*ppHead && (*ppHead)->val == val)
        return;
    Node * tmp = new Node(val); // new throws
    tmp->next = *ppHead;
    *ppHead = tmp;
}

【讨论】:

  • 干得好。我对头部进行特殊套管已经太久了!这是一种更清洁的方法。有点啊哈是我想要的!
【解决方案2】:

这行得通吗?

// Note the change from > to >=
while(cur->next && (val >= cur->next->val))
{   cur = cur->next;
}

if (val == cur->val)
{   return;
}

【讨论】:

  • 没错。我之前尝试过,其他东西一定是坏了。无论如何,有了 19K,我认为 Chris 应该得到提升。但你是对的。
【解决方案3】:

首先,如果您将其用于生产代码,您可能应该使用std::(如果可以的话)。

我对您的代码思考得越多,我就越认为您应该保留两个指针。基本上一个到当前的Node 和一个到以前的Node。如果cur == NULL,则在prev 之后插入。如果cur-&gt;value == val,返回。然后您可以检查是否cur-&gt;value &lt; val,如果是,则推进两个节点。

您目前有特殊代码来处理*ppHead == NULL。但是,如果您将 prev 改为 Node** curPtr,则不需要这样做。所以从curPtr=ppHeadcur=*curPtr 开始。那么上面的算法应该适用于整个事情。

或者作为刚刚发布代码的人,您可以将 ppHead 用作 curPtr 变量本身,将 (*ppHead) 用作 cur。不确定哪个更具可读性。

【讨论】:

    【解决方案4】:

    我会向 Node 添加一个方法来执行查找操作(*未经测试的代码):

    Node* Find(int value)
    {
        if( this.val == value ) return this;
        if( this.next == null ) return null;
        return next.Find(value);
    }
    

    然后在插入之前要检查是否存在:

    if( null == _head || null == _head.Find(value) )
        ... add value ...
    

    【讨论】:

    • 因为他试图做一个排序列表,搜索一个完全匹配可能没有帮助。
    • 我一定错过了指定列表排序的部分。
    猜你喜欢
    • 2019-04-13
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多