【问题标题】:What is the best way to reject duplicates in a sorted doubly linked list在排序的双向链表中拒绝重复项的最佳方法是什么
【发布时间】:2020-10-20 03:43:06
【问题描述】:

我正在尝试创建一个不插入重复项的排序双向链表,但我无法找到一种方法来执行此操作。我查看了有关如何删除重复项的帖子,但没有查看有关防止重复插入的帖子。

这是我必须在不拒绝重复的情况下插入和排序的代码。参数 dataIn 从 main (Student s = {{gpa, name}, ..., {gpa, name}} 中的预定义学生对象列表中获取值:

void StudentList::insertNode(Student dataIn)
{
    ListNode *newNode; // A new node pointer
    ListNode *pCur; // To traverse the list
    // Allocate a new node and store num there.
    newNode = new ListNode;
    newNode->stu = dataIn;
    newNode->forw = NULL;
    newNode->back = NULL;
    
    //Check if there is node in list
    if(head ->forw == NULL && head->back == NULL){
        head->forw = newNode;
        newNode->back = head;
        newNode->forw = head;
        head->back = newNode;
    }
    else{
        // Initialize pointers
        pCur = head->forw;
        // Find location: skip all nodes whose name is less than dataIn's name
        while (pCur != head && pCur->stu.name < dataIn.name)
        {
            pCur = pCur->forw;
        }
        // Insert the new node between pPre and pCur
        ListNode *pPre = pCur->back; // The previous node
        newNode->back = pPre;
        newNode->forw = pCur;
        pCur->back = newNode;
        pPre->forw = newNode;
    }
    // Update the counter
    count++;
}

有谁知道拒绝重复而不删除的方法?谢谢大家!

【问题讨论】:

  • 当您尝试某事但它不起作用时,请不要再问“什么是 XYZ 的最佳方式”。相反,问一个关于实际问题的问题。如果有更好的方法,有人可能会在确定您的问题的同时指出这一点。
  • 第 1 步是编写一个 bool StudentList::contains(const Student &amp; s) const 方法,如果列表中已经存在等于 sStudent,则返回 true。第二步是将if (contains(dataIn)) return; 添加到insert() 方法的顶部。
  • while (pCur != head &amp;&amp; pCur-&gt;stu.name &lt; dataIn.name)循环结束时,有三种可能。 1) pCur == head - 你绕了一圈,dataIn.name 比所有其他名字都小; 2) pCur-&gt;stu.name &gt; dataIn.name - 你找到了插入新名字的地方; 3) pCur-&gt;stu.name == dataIn.name - 已经存在同名节点,dataIn 是重复的,应该被拒绝。您不需要任何额外的数据结构。
  • 当您“检查列表中是否有节点”时,您在插入第一个节点之前执行if(head -&gt;forw == NULL) ... 但不是head == NULL?如果是,你不能做head-&gt;forwhead-&gt;back
  • “这就是插入发生的地方”——不完全是,当您更新 backforw 指针时,插入发生在 while 循环之后。但无论哪种方式都没有关系:while 循环找到了应该插入节点的位置,所以你可以在那个时刻(在更新 pCur 之后,或者在 while 循环之后)检查你是否找到了一个相等的节点。跨度>

标签: c++ vector iterator duplicates doubly-linked-list


【解决方案1】:

在已排序的双向链表中拒绝重复项的最佳方法是什么?

我建议延迟创建新的ListNode,直到您知道新节点不是重复的。

假设ListNode 看起来像这样

struct ListNode {        
    Student stu;
    ListNode *back;
    ListNode *forw;
};

并且当StudentList 为空时,您有一个headtail ListNode* 设置为nullptr,那么insertNode 函数可能如下所示:

bool StudentList::insertNode(const Student& dataIn) { // return true if node is inserted
    ListNode* prev = nullptr;
    ListNode* pCur = head;

    // search for a good insertion spot
    for(; pCur; prev = pCur, pCur = pCur->forw) {
        if(dataIn.name == pCur->stu.name) return false; // equal, reject
        if(dataIn.name < pCur->stu.name) break;         // found a good spot before pCur
    }

    // delayed creation until here:
    ListNode* newNode = new ListNode{dataIn, prev, pCur};

    // linking        
    if(prev) prev->forw = newNode;
    else head = newNode;
    
    if(pCur) pCur->back = newNode;
    else tail = newNode; // comment this line out if you don't have a "tail"

    ++count;

    return true; // node inserted
}

【讨论】:

  • 这是我正在寻找的简单解决方案。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 1970-01-01
  • 2012-03-30
  • 2013-03-11
  • 2010-12-16
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多