How to delete two items in a row in a linked list

别来无恙 提交于 2019-12-02 10:51:10

问题


void delete_double (LN<T>*& l) {
    if (l == nullptr)
        return;

    LN<T> *p = l;
    while ( p -> next != nullptr && p -> next -> next != nullptr)
    {
        if (p -> value == p -> next -> value) // the current value is equal to the next value in the linked list 
        {
            if (p == l)                     // when the first two values are the same                                        // not sure if it is correct
            {
                l = l -> next -> next;
            }
            else                            // Problem should be here
            {
                LN<T> *to_delete = p;       //  Also tried this (doesn't work)
                p = p->next;
                delete to_delete;           //  LN<T>* to_delete = p;
                                            //  LN<T>* to_delete2 = p -> next;
                LN<T> *to_delete1 = p;      //  l = to_delete2 -> next;
                p = p->next;                //  delete to_delete;
                delete to_delete1;          //  delete to_delete2;
            }
        }
        else
        {
            p = p-> next;
        }
    }
}
//  Image below is my output

enter image description here

Hi, I am writing a function that would delete two values in a row in a linked list if the two values are the same. My code seems to stop working when the input is something like "1 -> 2 -> 3 -> 3 -> 4 -> nullptr".(the output should be 1 -> 2 -> 4 -> nullptr). It exits without giving me any error. And I went through the debug line by line, It just suddenly exits and showed "variables are not available".

I am guessing it is the problem that when I delete p, the l points to garbage, which causes the problem. So I tried a different way to make l point to to_delete -> next. But it still does not work.

I have tried so many hours to fix it and the debug won't even help. Can someone please help? Thank you so much!


回答1:


I have simplified the code above, the logic you have above also wont help you remove multiple duplicates. So lets look at the code below and dissect it:

   void delete_double(LN<T>*& l) {

        if (l == nullptr)
            return;

        LN<T> *p = l;
        LN<T> dummy(0);
        dummy.next = l;
        p = &dummy;

        LN<T> *temp;
        LN<T> *duplicate;
        LN<T> *prev;

        while (p != nullptr && p->next != nullptr)
        {
            temp = p;
            while (p != nullptr && temp->next != nullptr)
            {
                if (p->value == temp->next->value)
                {
                    duplicate = temp->next;
                    temp->next = temp->next->next;
                    delete duplicate;

                    duplicate = p;
                    prev->next = p->next;
                    p = prev;
                    delete duplicate;

                    temp = p;
                }
                else
                {
                    break;
                }
            }
            prev = p;
            p = p->next;
        }

        l = dummy.next;
    }

There seems to be a need for a dummy node at the start because if we have 1 -> 1 - > 2 we need to delete the first two and point to the correct head which is a 2. In order to avoid this confusion is better to keep a dummy node at the start and at the end just set the output of your list to be p = dummy.next, which is the actual start of your list.

I have defined some temporaries, temp and duplicate, temp to help me navigate further in the list and duplicate to hold the duplicate value, move the pointer to next and delete the node. prev is the previous pointer to the node just before the duplicates.

Each node in the list, temp = p I move forward until looking for the adjacent match p->value == temp->next->value if there is a match I delete the current node and the one I found ahead of it. I use the prev tracker to restore the order of the list by correctly setting its next, else I break from my inner loop and move on to the next value, the outer loop p = p->next.

I am not sure about your LN<T> struct so I have gone ahead with what I think it is.

Demo Link




回答2:


Before or after you delete p, the item before p should point to the item after the two deleted items. Otherwise, the link list will broken.

Furthermore, for the while-loop, you may only stop when you arrive the last item. Otherwise, if the last two items are the same, you cannot correctly delete it.

Here is my version. I used a dummy item to point to the item before the current compared item. Notice this cannot deal with 3 items in a row.

void delete_double (LN<T>*& l) {
    if (l == nullptr)
        return;
    LN<T> *dummy = new LN<T>;
    dummy -> next = l;
    while ( dummy -> next != nullptr && dummy -> next -> next != nullptr) // search until the last but two item
    {
        if (dummy -> next -> value == dummy -> next -> next -> value) // the current value is equal to the next value in the linked list
        {
            dummy -> next = dummy -> next -> next -> next;  // link the item after dummy to the item after the deleted items         
        }
        dummy = dummy -> next; // move dummy to the next, notice that this cannot deal with 3 items in a row
    }
    return;
}


来源:https://stackoverflow.com/questions/46822375/how-to-delete-two-items-in-a-row-in-a-linked-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!