Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.05.2023, 14:09   #1
natatttt
 
Регистрация: 08.04.2023
Сообщений: 9
По умолчанию Удалить все эл-ты двусвязного списка, находящиеся между его минимальным и максимальным эл-тами

Помогите, пожалуйста
Требуется удалить все эл-ты двусвязного списка, находящиеся между его минимальным и максимальным эл-тами. Информационную часть в операционной системе не перемещать. В конце освободить всю динамическую память.

Минимальный и максимальный эл-ты я нашла, а вот удаление (void del_between()) не очень понимаю как реализовать
Код:
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <io.h>
#include <iomanip>
using namespace std;
 
struct TNode
{
    int inf; //информационная часть
    TNode* left; //адресная часть
    TNode* right; //адресная часть
};
 
struct list //работа со списком
{
    TNode* front = nullptr; // Указатель на начало очереди
    TNode* back = nullptr; // Указатель на конец очереди
 
    // Проверка наличия элементов в очереди
    bool empty() 
    {
        if (front) return false;
        else return true;
    }
 
    // Добавление элемента в очередь
    void push(int inf) 
    {
        TNode* spt = new TNode;
        spt->inf = inf;
        spt->right = nullptr;
        if (!front) 
        {
            spt->left = nullptr;
            front = back = spt;
            return;
        }
        back->right = spt;
        spt->left = back;
        back = spt;
    }
 
    // Удаление элемента из очереди
    void pop() 
    {
        TNode* spt = front;
        front = front->right;
        delete spt;
        if (!front) back = nullptr;
        else front->left = nullptr;
    }
 
    // Вывод очереди
    void print() 
    {
        TNode * spt = front;
        while (spt != nullptr) 
        {
            cout << spt->inf << " ";
            spt = spt->right;
        }
    }
 
    //поиск минимального эл-та
    TNode* search_min()
    {
        TNode* min = front;
        TNode* spt = front;
        while (spt != nullptr)
        {
            if (spt->inf < min->inf) min = spt;
            spt = spt->right;
        }
        return min;
    }
 
    //поиск максимального эл-та
    TNode* search_max()
    {
        TNode* max = front;
        TNode* spt = front;
        while (spt != nullptr)
        {
            if (spt->inf > max->inf) max = spt;
            spt = spt->right;
        }
        return max;
    }
 
    void del_between()
    {
        TNode* min = search_min();
        TNode* max = search_max();
        TNode* spt = front;
 
 
 
    }
};
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    list s;
    int n;
    cout << "Введите кол-во эл-тов списка: ";
    cin >> n;
    cout << "___________________________________" << endl;
    int k;
    for (int i = 0; i < n; i++)
    {
        cout << "Введите " << i + 1 << " эл-т списка : ";
        cin >> k;
        s.push(k);
    }
    cout << "___________________________________" << endl;
    cout << "Введенные эл-ты списка: " << endl;
    s.print();
    cout << endl;
    cout << "___________________________________" << endl;
    TNode* min = s.search_min();
    cout << "Минимальный эл-т списка: " << min->inf << endl;
    TNode* max = s.search_max();
    cout << "Максимальный эл-т списка: " << max->inf << endl;
    cout << "___________________________________" << endl;
    s.del_between();
    cout << endl;
    cout << "Cписок после удаления эл-тов: " << endl;
    s.print();
    cout << endl;
    while (!s.empty()) s.pop();
    return 0;
}
natatttt вне форума Ответить с цитированием
Старый 21.05.2023, 17:54   #2
maks1331
Форумчанин
 
Аватар для maks1331
 
Регистрация: 20.12.2016
Сообщений: 270
По умолчанию

Если оставаться в рамках текущей реализации, то я бы добавил счетчик позиции для min и max, чтобы понимать, left или right указатель изменять у соответствующих TNodes.

Как вариант, можно добавить два приватных члена класса к list. Не забывая очищать их после обрезания и проверять перед обрезанием, на случай, если обрезать нечего.

Код:
void del_between()
{
    TNode* min = search_min();
    TNode* max = search_max();

    if (min_pos == max_pos) {
    	std::cout << "Пустая область между min и max" << std::endl;
    	return;
    }

    if (min_pos > max_pos) {
    	TNode* temp = min;
    	min = max;
    	max = temp;
    }

    TNode* saveToFree;
    while (min->right != max) {
    	saveToFree = min->right;
    	min->right = min->right->right;
    	free(saveToFree);
    }

    min_pos = 0;
    max_pos = 0;
}
А так, я бы оставил один метод del_between_min_max и отказался от дополнительных членов класса.

Так же стоит указать, что код ищет только первые минимум и максимум.
И на сладкое, я бы написал функцию для тестирования, простейший unit test, типо такого:

Код:
#include <vector>

bool UnitTest(const std::vector<int>& input, const std::vector<int>& output)
{
    list s;
    for (const auto value : input) {
        s.push(value);
    }
    s.del_between();

    TNode* node = s.front;
    for (const auto value : output) {
        if (node == nullptr) {
            std::cout << "Тест провален, итоговый список короче, чем ожидалось" << std::endl;
            return false;
        }
        if (node->inf != value) {
            std::cout << "Тест провален, значение списка: " << node->inf << " не равно ожидаемому: " << value << std::endl;
            return false;
        }
        node = node->right;
    }

    if (node != nullptr) {
        std::cout << "Тест провален, итоговый список длиннее, чем ожидалось" << std::endl;
        return false;
    }

    std::cout << "Тест пройден" << std::endl;
    return true;
};
Код:
if (!UnitTest({ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }, { 1, 5, 1, 2, 3, 4, 5 })
    || !UnitTest({ 1, 2, 3, 4, 5, 0, 1, 2, 3, -1, 4, 5 }, { 1, 2, 3, 4, 5, -1, 4, 5 })
    || !UnitTest({ 5, 4, 3, 2, 1, 5, 4, 3, 2, 1 }, { 5, 1, 5, 4, 3, 2, 1 })
    || !UnitTest({ 5, 4, -1, 3, 2, 1, 0, 6, 5, 4, 3, 2, 1 }, { 5, 4, -1, 6, 5, 4, 3, 2, 1 })
    || !UnitTest({ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }) 
    || !UnitTest({ 0 }, { 0 })
    || !UnitTest({ 0, 1 }, { 0, 1 }) 
    || !UnitTest({ 1, 0 }, { 1, 0 })) {

    return -1;
}
формошлеп.рф
witech.su

Последний раз редактировалось maks1331; 21.05.2023 в 18:32.
maks1331 вне форума Ответить с цитированием
Старый 21.05.2023, 21:48   #3
natatttt
 
Регистрация: 08.04.2023
Сообщений: 9
По умолчанию

А что делает функция free(saveToFree)?
я не очень понимаю
natatttt вне форума Ответить с цитированием
Старый 21.05.2023, 22:06   #4
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,343
По умолчанию

Думаю, free приблудилась из C, делайте delete. Еще стоит добавить проверку front в функции pop, а не лезть сразу по указателю front->right, т.к. список может быть пуст.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 22.05.2023, 15:29   #5
natatttt
 
Регистрация: 08.04.2023
Сообщений: 9
По умолчанию

У меня еще иногда высвечивается исключение в строке
Код:
min->right = min->right->right;
"Вызвано исключение: нарушение доступа для чтения.
min->right было nullptr."
natatttt вне форума Ответить с цитированием
Старый 22.05.2023, 17:06   #6
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,343
По умолчанию

Цитата:
Сообщение от natatttt Посмотреть сообщение
иногда высвечивается исключение
Почему-то пролетаете мимо максимума до конца списка. Как выставляете min_pos в search_min и max_pos в search_max?
А еще в del_between после цикла нужно сделать max->left = min, чтобы сохранить двусвязность списка.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Произведение между максимальным и минимальным значениями массива Maxim93m Общие вопросы C/C++ 4 19.11.2014 19:55
Удалить элементы в массиве, стоящие между максимальным и минимальным элементами Tkas Помощь студентам 0 04.03.2012 16:50
Дан массив [3*4]. Определить разницу между максимальным и минимальным значениями. vbchristy46 Помощь студентам 7 15.06.2010 23:29
Разность между максимальным и минимальным значениями StudeHt Помощь студентам 7 23.04.2009 22:26