@peresvet_koltyrin

Проблема с двусвязным списком?

Всееем добрый вечер! Подскажите, пожалуйста, в чём здесь ошибка? Код запускается и работает, но работает немного неправильно.

Условие задачи таково: Создать двусвязный список, содержащий целые числа. Удалить все элементы,
совпадающие с последним элементом списка.
Например, для списка 5 2 9 1 3 7 9 2 9, результат должен быть 5 2 1 3 7 2.

Я код написал, запускаю, а программа просто заместо последнего элемента пишет 0, помогите, пожалуйста...

#include <iostream>
using namespace std;
 
int z;
struct list {
    int inf;
    list* next;
    list* prev;
};
 
/*----------------Функция добавления элемента в список-----------------*/
void push(list*& h, list*& t, int x) {
    list* r = new list; // создаем новый элемент
    r->inf = x;
    r->next = NULL;
    if (!h && !t) { // если список пустой
        r->prev = NULL;
        h = r;// теперь h = голова
    }
    else {
        t->next = r; // если список не пустой, то хвост двигается дальше на r
        t->prev = t; // хвостом становится предыдущий t
    }
    t = r; // Теперь r хвост
 
}
 
/*----------------Функция печати списка-----------------*/
 
void print(list* h, list* t) {
    list* p = h; // указатель на голову
    while (p) {// пока не дошли до конца
        cout << p->inf << " "; // выводим элемент
        p = p->next; // двигает список дальше
    }
}
 
 
 
/*---------Функция удаления элементов из начала, конца, середины----------*/
 
void del_node(list*& h, list*& t, list* r) {
    if (r == h && r == t) { // единственный элемент списка
        h = t = NULL;
    }
    else if (r == h) { // удаляем голову списка
        h = h->next; // сдвигаем голову
        h->prev = NULL;
    }
    else if (r == t) { // удаляем хвост списка
        t = t->prev;
        t->next = NULL;
    }
    else { // удаление из середины
        r->next->prev = r->prev; //Связываем r->prev и r->next.Предыдущим для r->next становится r->prev
        r->prev->next = r->next; //Связываем r->prev и r->next.Следующим для r->prev становится r->next
    }
    delete r;
}
 
/*-----------------Удаление списка------------*/
 
 
void result(list*& h, list*& t) { // функция удаления всех элементов равных последнему
    list* p = h;
    while (p) {
        if (p->next == NULL) {
            p->inf = z;
        }
        p = p->next;
    }
    while (p) {
        if (p->inf == z) {
            del_node(h, t, p);
        }
        p = p->next;
    }
}
int main() {
    setlocale(LC_ALL, "rus");
    cout << "Введите количество элементов списка" << endl;
    int n;
    cin >> n;
 
    list* h = new list; // инициализация
    list* t = new list;
 
    h = NULL;
    t = NULL;
 
    for (int i = 0; i < n; i++) {
        int temp;
        cin >> temp;
        push(h, t, temp);
    }
    result(h, t);
    print(h, t);
 
    system("pause");
    return 0;
}
  • Вопрос задан
  • 91 просмотр
Пригласить эксперта
Ответы на вопрос 2
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Ошибка в push: prev предпоследнего элемента указывает на него же, а prev у последнего всегда null.

Ошибка в result: вы переписываете значение последнего элемента зачем-то.

Потом в цикле вы сначала удаляете элемент p, а потом переходите по p->next, читая уже удаленную память. Но это не беда, потому что второй цикл ни разу не выполняется (почему, догадаетесь?).

В main вы зачем-то выделяете h и t, только чтобы сразу же устроить утечку этой памяти.
Ответ написан
@res2001
Developer, ex-admin
В del_node() происходит освобождение памяти, а затем в result вы обращаетесь к освобожденной памяти (второй цикл):
p = p->next;
Зачем в result первый цикл? И зачем в программе z?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы