это работает сейчас?

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

те описание изображения здесь

Привет, я пишу функцию, которая удаляет два значения в строке в связанном списке, если два значения одинаковы. Кажется, мой код перестает работать, когда ввод выглядит как «1 -> 2 -> 3 -> 3 -> 4 -> nullptr» (вывод должен быть 1 -> 2 -> 4 -> nullptr). Он выходит без каких-либо ошибок. И я прошел отладку построчно, он просто неожиданно завершил работу и показал, что «переменные недоступны».

Я предполагаю, что это проблема, что, когда я удаляю p, l указывает на мусор, который вызывает проблему. Поэтому я попробовал другой способ заставить l указать на to_delete -> next. Но это все равно не работает.

Я столько часов пытался это исправить, и отладка даже не помогла. Может кто-нибудь, пожалуйста, помогите? Спасибо вам большое!

 Samer Tufail19 окт. 2017 г., 06:21
Вы бы удалили все значения, которые появляются дважды? или это просто 1 пара?
 perreal19 окт. 2017 г., 05:35
А ну понятно. Также, когда вы удаляете элемент, вам нужно изменить следующий указатель элемента, предшествующего ему.
 PaulMcKenzie19 окт. 2017 г., 06:35
@lykdogи отладка даже не поможет - Похоже, вы должны сначала проработать это на бумаге, используя поля для данных и строки для ссылок, прежде чем писать какой-либо код. Тогда для отладки нужно просто посмотреть, где ваш код идет против того, что у вас есть на бумаге.

Ответы на вопрос(2)

элемент перед p должен указывать на элемент после двух удаленных элементов. В противном случае список ссылок будет поврежден.

Кроме того, для цикла while вы можете остановиться, только когда прибудете последний элемент. В противном случае, если последние два элемента совпадают, вы не сможете правильно удалить его.

Вот моя версия. Я использовал фиктивный элемент, чтобы указать на элемент перед текущим сравниваемым элементом. Обратите внимание, что это не может иметь дело с 3 предметами подряд.

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;
}
 jeffzhao19 окт. 2017 г., 06:53
это работает сейчас?
Решение Вопроса

и приведенная выше логика также не поможет вам удалить несколько дубликатов. Итак, давайте посмотрим на код ниже и разберем его:

   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;
    }

Кажется, существует необходимость в фиктивном узле в начале, потому что если у нас есть 1 -> 1 -> 2, нам нужно удалить первые два и указать на правильную головку, которая равна 2. Во избежание этой путаницы лучше чтобы держать фиктивный узел в начале и в конце, просто установите вывод вашего списка равным p = dummy.next, который является фактическим началом вашего списка.

Я определил некоторые временные,temp а такжеduplicate, чтобы помочь мне перемещаться дальше по списку и дублировать, чтобы сохранить повторяющееся значение, переместить указатель на следующий и удалить узел.prev предыдущий указатель на узел перед копиями.

Каждый узел в списке,temp = p Я двигаюсь вперед, пока не ищу соседний матчp->value == temp->next->value если есть совпадение, я удаляю текущий узел и тот, который я нашел перед ним. Я используюprev трекер, чтобы восстановить порядок списка, правильно установив егоnextиначе я вырываюсь из своего внутреннего цикла и перехожу к следующему значению, внешнему циклуp = p->next.

Я не уверен в твоихLN<T> структура, поэтому я пошел вперед с тем, что я думаю, что это.

Демо-ссылка

 Samer Tufail19 окт. 2017 г., 07:36
Проверьте, проходит ли это ваши тесты, и я тем временем обновлю объяснение
 Samer Tufail19 окт. 2017 г., 07:00
Это должно быть легко исправить, я неправильно понял оригинал, с
 Samer Tufail19 окт. 2017 г., 07:49
Он также проходит 1-> 1-> 2-> 3. Позвольте мне добавить ссылку на демо
 Samer Tufail19 окт. 2017 г., 07:58
@lykdog проверьте ответ Я добавил вывод демонстрационной ссылки, как и ожидалось, для 1-> 1-> 2-> 3 вы получите 2-> 3, вы можете поэкспериментировать с ним в редакторе, он все равно будет работать.

Ваш ответ на вопрос