【问题标题】:Trying to fix error in a program for removing duplicates in linked list尝试修复程序中的错误以删除链表中的重复项
【发布时间】:2020-08-06 17:03:06
【问题描述】:

我正在执行一个程序,使用两个循环从未排序的链表中删除重复项。

该程序包括两个structs,用于定义NodenewNode。此外,它还包括两个用户定义的函数removeDuplicates 用于删除链表的重复项和printList 用于打印列表。

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

struct Node *newNode(int data) {
       Node *temp = new Node;
       temp->data = data;
       temp->next = NULL;

       return temp;
};

/* Function to remove duplicates from an unsorted linked list */
void removeDuplicates(struct Node *start) {
     struct Node *ptr1, *ptr2, *dup;
     ptr1 = start;

     while (ptr1 != NULL && ptr1->next != NULL) {
           ptr2 = ptr1;

           while (ptr2->next != NULL) {
                 if (ptr1->data == ptr2->next->data) {
                    dup = ptr2->next;
                    ptr2->next = ptr2->next->next;
                    delete (dup);
                 } else
                    ptr2 = ptr2->next;

                 ptr1 = ptr1->next;
           }
     }
}

void printList(struct Node *node) {
     while (node != NULL) {
           printf("%d  ", node->data);
           node = node->next;
     }

     printf("\n");
}

我运行了几个测试用例,

案例 1 输入:12->11->12->21->41->43->21

   Output(from the program) : 12->11->12->21->41->43->21
       Required Output : 12->11->21->41->43
int main() {
    struct Node *start = newNode(12);
    start->next = newNode(11);
    start->next->next = newNode(12);
    start->next->next->next = newNode(21);
    start->next->next->next->next = newNode(41);
    start->next->next->next->next->next = newNode(43);
    start->next->next->next->next->next->next = newNode(21);

    printf("Linked List before removing duplicates");
    printList(start);

    removeDuplicates(start);

    printf("Linked List after removing duplicates");
    printList(start);
}

案例 2 输入:10->12->11->11->12->11->10

       Output : 10->12->11
int main() {
    struct Node *start = newNode(10);
    start->next = newNode(12);
    start->next->next = newNode(11);
    start->next->next->next = newNode(11);
    start->next->next->next->next = newNode(12);
    start->next->next->next->next->next = newNode(11);
    start->next->next->next->next->next->next = newNode(10);

    printf("Linked List before removing duplicates");
    printList(start);

    removeDuplicates(start);

    printf("Linked List after removing duplicates");
    printList(start);
}

该程序适用于一个测试用例,而不适用于其他用例。我在代码中遗漏了什么?

【问题讨论】:

  • 您是否尝试过在调试器中逐行运行代码,同时监控所有变量的值?如果没有,那么您可能想阅读以下内容:What is a debugger and how can it help me diagnose problems? 您可能还想阅读以下内容:How to debug small programs
  • 不要做delete(dup); 你不会在任何地方做new。另外,制作一个minimal reproducible example
  • ptr1 = ptr1->next; 这行不应该在外循环的末尾吗?目前,它位于内部循环的末尾。
  • 警告:好像有人在教你 C 并告诉你它是 C++。别被骗了。 Upgrade your reference materials 以便您了解差异。
  • 如果你让newNodeNode *newNode(int data, Node * next){ Node *temp = new Node; temp->data = data; temp->next = next; return temp; } 变得更聪明一点,start->next->next->next->next->next->nexts 的巨大质量可以简化为 start = newNode(1, newNode(2, newNode(3, NULL))) 之类的东西

标签: c++ linked-list


【解决方案1】:

问题就在这里:

while ((ptr1 != NULL) && (ptr1->next != NULL))
{
        ptr2 = ptr1;
        while (ptr2->next != NULL)
        {
            // delete if duplicate
            ptr1 = ptr1->next;
        }
}

您正在删除重复项的循环内移动ptr1,但需要在链表中的每个节点移动一次:

while ((ptr1 != NULL) && (ptr1->next != NULL))
{
        ptr2 = ptr1;
        while (ptr2->next != NULL)
        {
            // delete if duplicate
        }
        ptr1 = ptr1->next;  // move ptr1 here
}

这是demo

【讨论】:

    【解决方案2】:
    /* Function to remove duplicates from an unsorted linked list*/
    void removeDuplicates(struct Node *start)
    {
        struct Node *ptr1 = start;
    
        while (ptr1) {
       
            struct Node *ptr2     = ptr1->next;
            struct Node *ptr2prev = ptr1;
    
            while (ptr2) {
    
                if (ptr1->data == ptr2->data) {
                    
                    struct Node *tmp = ptr2;
    
                    ptr2prev->next   = ptr2->next;
                    ptr2             = ptr2->next;
                    
                    delete tmp;
                    continue;
                }  
    
                ptr2 = ptr2->next;
                ptr2prev = ptr2prev->next;
            }  
    
            ptr1 = ptr1->next;
        }  
    }
    

    【讨论】:

    • 注意:您可以大大减少使用指针到指针所需的簿记量。请参阅社区添加 in this answer.
    • @user4581301。谢谢
    【解决方案3】:

    简短的回答。下面的代码将起作用。

    void removeDuplicates(struct Node *start)
    {
        struct Node *ptr1, *ptr2, *ptr3;
        ptr1 = start;
        while ((ptr1 != NULL) )
        {
            ptr2 = ptr1->next;
            ptr3=ptr1; //used inside the next while loop
            while (ptr2 != NULL)
            {
                if ((ptr1->data) == (ptr2->data))
                {
                    ptr3->next = ptr2->next;
                    delete (ptr2);
                    ptr2 = ptr3->next
                }
                else
                {
                    ptr3 = ptr2; //prev of next ptr2
                    ptr2 = ptr2->next;
                }
            }
            ptr1=ptr1->next;
        }
    }
    

    您正在第一个 while 循环中修改变量 ptr1。由于您必须将第一个元素与链表的所有剩余元素进行比较,因此您应该只在内部 while 循环完成后更改“ptr1”。否则,将第一个节点与第二个节点进行比较,然后将第一个节点修改为下一个节点。所以第一个节点不会与其他节点进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 2013-07-12
      • 2021-05-04
      相关资源
      最近更新 更多