Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/55: Рейтинг темы: голосов - 55, средняя оценка - 4.60
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338

Реализация функций erase,insert,clear - для односвязного списка

17.09.2020, 04:36. Показов 13028. Ответов 133
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть следующая реализация односвязаного списка:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class List
{
private:
    size_t size;
    //------------------------------
        template<class T>
        class Node
        {
        public:
            Node* ptrNext;
            T data;
            Node(T data_ = T(), Node* ptrNext_ = nullptr)
            {
                this->data = data_;
                this->ptrNext = ptrNext_;
            }
        };
    //------------------------------
public:
    List();
    ~List();    
    Node<T>* head;
    void push_back(T data_);
    void erase(const size_t index);
    void insert(const size_t position, T date_);
    void clear();
    void lout();
    int getSize() { return size; };
    void randIntInit(size_t count,int min,int max);
    T& operator[](const size_t index);
    
};
И есть следующие функции написанные мною без заглядывания в любой источник знаний:

erase - удаление
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template<class T>
void List<T>::erase(const size_t index)
{
        size_t counter{ 0 };
        Node<T>* current = this->head;
        Node<T>* ptrprevious = this->head;
        while (current != nullptr)
        {
            if (counter == index-1)
            {
                if (index-1 == 0)
                {
                    this->head = current->ptrNext;
                    delete current;
                    size--;
                    break;
                }
                else
                {
                    ptrprevious->ptrNext = current->ptrNext;
                    delete current;
                    size--;
                    break;
                }
            }
            else
            {
                ptrprevious = current;
                current = current->ptrNext;
                counter++;
            }
 
        }
}
//------------------------------
lout - вывод
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<class T>
void List<T>::lout()
{   
    if (this->getSize()>0)
    {
        cout << "List elements count: " << this->getSize() << endl;
        Node<T>* current = this->head;
        size_t fakesize{ 1 };
        while (current != nullptr)
        {
            cout << fakesize << "::" << current->data << endl;
            current = current->ptrNext;
            fakesize++;
        }
        cout << endl;
    }
    else
    {
        cout << "List empty!" << endl;
    }
}
//------------------------------
clear - полная очистка
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class T>
void List<T>::clear()
{
    Node<T>* current = this->head;
    Node<T>* ptrprevious = this->head;
    while (current != nullptr)
    {   
        ptrprevious = current;
        current = current->ptrNext;
        delete ptrprevious;
        size--;
    }
}
//------------------------------
insert - вставка на позицию
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
template<class T>
void List<T>::insert(const size_t position, T date_)
{
    Node<T>* current = this->head;
    Node<T>* ptrprevious = this->head;
    size_t counter{ 0 };
    while (current != nullptr)
    {
        if (counter == position-1)
        {
            if (position == 1)
            {
                this->head = new Node<T>(date_);
                this->head->ptrNext = ptrprevious;
                size++;
                break;
            }
            else
            {
                Node<T>* NewNode = new Node<T>(date_, current);
                ptrprevious->ptrNext = NewNode;
                size++;
                break;
            }
        }
        else
        {
            ptrprevious = current;
            current = current->ptrNext;
            counter++;
        }
    }
}
В функциях я натыкал как чувствую - лишних операторов if:
В функции erase оператор if нужен чтобы определить когда пытаются удалить первый элемент и изменить реализацию удаления.
В функции insert оператор if нужен чтобы определить когда пытаются добавить элемент в начало списка и "сдвинуть" список с заменой главного элемента.
В функции lout ( вывод ) оператор if нужен чтобы определить когда список пустой.



Это допустимая/нормальная реализация этих функций или нужно их изменить? ( Можно ли сделать красивее без такого количества if-ов или и так адекватно? )
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.09.2020, 04:36
Ответы с готовыми решениями:

Метод insert и erase для шаблонного класса списка
Всем привет. Подскажите как реализовать методы добавления и удаление элемента из указанной позиции в односвязном списке Вот мое удаление:...

Реализация функций reserve и clear для вектора
Мне нужно самой написать реализацию. От что у меня есть: template&lt;typename T&gt; void Vector&lt;T&gt;::PopBack() { mVector.~T(); ...

Реализация односвязного списка
Здравствуйте, проверьте код, пожалуйста, задание по односвязным спискам. Создать односвязный список с помощью массива структур....

133
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338
23.09.2020, 20:10  [ТС]
Студворк — интернет-сервис помощи студентам
oleg-m1973, хочу переспросить за условие следующей функции ( именно из-за него удалялся не тот элемент ):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <typename T>
typename List<T>::Node* List<T>::find_previous(T data_)
{
        if (this->head->data==data_)
 
        {
            return nullptr;
        }
        else
        {
            Node* current = this->head;
            while (current->ptrNext && current->ptrNext->data != data_)
            {       
                current = current->ptrNext;
            }
            return current;
        }
}
C++
1
current->ptrNext->data != data_)
Если я не ошибаюсь, с таким условием сравниваются данные не от следующего от current элемента, а сравниваются от следующего от следующего от current элемента??
Я попробовал следующее условие:
C++
1
while (current->ptrNext && current->data != data_)
И ошибка с удалением элемента со значением 71 вместо элемента со значением 87 - ушла.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.09.2020, 20:18
Цитата Сообщение от SkYMaaN Посмотреть сообщение
Если я не ошибаюсь, с таким условием возвращаются данные не от следующего от current элемента, а возвращаются от следующего от следующего от current элемента??
Здесь всё правильно. Проверь
C++
1
2
3
auto *node = lst.find_previous(87);
std::cout << node->data << std::endl;
std::cout << node->ptrNext->data << std::endl;
Добавлено через 45 секунд
Покажи push_back и remove_next
0
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338
23.09.2020, 20:24  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Покажи push_back и remove_next
C++
1
2
3
4
5
6
7
8
9
10
11
12
template<class T>
void List<T>::remove_next(Node* ptr)
{   
    Node* current = this->head; 
    while (current->ptrNext != nullptr && current->ptrNext != ptr)
    {
        current = current->ptrNext;         
    }
    current->ptrNext = ptr->ptrNext;
    delete ptr;  
    size--;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<class T>
void List<T>::push_back(T data_)
{
    if (head == nullptr) 
    {
        head = new Node(data_);  
    }
    else  
    {
        Node* current = this->head;
        while (current->ptrNext != nullptr)
        {
            current = current->ptrNext; 
        }
    
        current->ptrNext = new Node(data_); 
    }
    size++;
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.09.2020, 20:26
Скорее это происходит потому, что ты так и не исправил вот это
Цитата Сообщение от SkYMaaN Посмотреть сообщение
Node* current = this->head;
            Node* ptrprevious = this->head;
            while (current->ptrNext && current->ptrNext->data != data_)
0
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338
23.09.2020, 20:27  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
std::cout << node->data << std::endl;
71
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
std::cout << node->ptrNext->data << std::endl;
87
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.09.2020, 20:27
Цитата Сообщение от SkYMaaN Посмотреть сообщение
Node* current = this->head;
    while (current->ptrNext != nullptr && current->ptrNext != ptr)
Это что за жесть?
0
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338
23.09.2020, 20:28  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Node* ptrprevious
такая переменная осталась только в функциях insert and erase , ещё не добрался до их исправления
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.09.2020, 20:31
C++
1
2
3
4
5
6
7
8
9
10
11
template<class T>
void List<T>::remove_next(Node* node)
{   
    auto *p = node->ptrNext;
    if (p)
    {
        node->ptrNext = p->ptrNext;
        delete p;
        size--;
    }
}
Добавлено через 2 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template<class T>
void List<T>::remove_next(Node* node)
{   
    if (!node)
    {
        auto p = head;
        head = head->ptrNext;
        delete p;
        size--;
    }
    else
    {
        auto *p = node->ptrNext;
        if (p)
        {
            node->ptrNext = p->ptrNext;
            delete p;
            size--;
        }
    }
}
1
 Аватар для SkYMaaN
25 / 19 / 9
Регистрация: 05.04.2019
Сообщений: 338
23.09.2020, 20:39  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
if (!node)
Как это логически прочитать: "если указателя нету?" - find_previous - вернула nullptr потому что элемент первый?

Как до меня дошло, то вся эта страшная реализация заменяется парой строчек кода с использованием функций remove_next and find_previous?:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template<class T>
void List<T>::erase(const size_t index)
{
    size_t counter{ 0 };
        Node* current = this->head;
        Node* ptrprevious = this->head;
        while (current != nullptr)
        {
            if (counter == index-1)
            {
                if (index-1 == 0)
                {
                    this->head = current->ptrNext;
                    delete current;
                    size--;
                    break;
                }
                else if (index-1 == this->getSize())
                {
                    ptrprevious->ptrNext = nullptr;
                    delete current;
                    size--;
                    break;
                }
                else
                {
                    ptrprevious->ptrNext = current->ptrNext;
                    delete current;
                    size--;
                    break;
                }
            }
            else
            {
                ptrprevious = current;
                current = current->ptrNext;
                counter++;
            }
 
        }
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.09.2020, 20:59
Цитата Сообщение от SkYMaaN Посмотреть сообщение
Как это логически прочитать: "если указателя нету?" - find_previous - вернула nullptr потому что элемент первый?
Ну да, if (node == nullptr)
Иначе каким образом ты собираешься указать на элемент предыдущий первому?

Добавлено через 18 минут
Цитата Сообщение от SkYMaaN Посмотреть сообщение
Как до меня дошло, то вся эта страшная реализация заменяется парой строчек кода с использованием функций remove_next and find_previous?:
Ну да, только параметр find_prev нужен другой. Лучше там сделать предикат
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
template <typename T> template <typename TFunc>
typename List<T>::Node* List<T>::find_prev_if(TFunc &&pred)
{
    if (head->data==data_)
        return nullptr;
 
    Node* current = this->head;
    while (current->ptrNext && !pred(current->ptrNext->data))
    {       
        current = current->ptrNext;
    }
    return current;
}
 
template <typename T>
typename List<T>::Node* List<T>::find_prev(const T &data)
{
    return find_prev_if([&data](const T &val)
    {
        return data == val;
    });
}
 
template<class T>
void List<T>::erase(size_t index)
{
    auto *node = find_prev_if([&index](const T &val)
    {
        return (index--) == 0;
    });
 
    remove_next(node);
}
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2020, 01:22
del
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.09.2020, 12:02
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
template <typename T> template <typename TFunc>
typename List<T>::Node* List<T>::find_prev_if(TFunc &&pred)
{
    if (head->data==data_)
        return nullptr;
Да, здесь ошибся
C++
1
2
    if (pred(head->data))
        return nullptr;
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2020, 17:58
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Да, здесь ошибся
Идея с предикатом реализуема, но связывает контейнер некоторыми знаниями о контенте. Впрочем, это возможно. Тогда имело бы смысл сделать предикат параметром шаблона (со значением по умолчанию std::equal_to<T> ). Но тогда, это бинарная функция. Может я не понял, что происходит?

Не по теме:

и жуть как хочется увидеть шаблонный класс слинкованный как DLL

0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.09.2020, 19:11
Цитата Сообщение от IGPIGP Посмотреть сообщение
Тогда имело бы смысл сделать предикат параметром шаблона (со значением по умолчанию std::equal_to<T> )
Нет, в функциях предикаты не делают параметром шаблона, должен быть именно параметр функции. Другое дело, что я здесь слегка упростил. Обычно я делаю вот так
C++
1
2
3
4
5
6
template <typename T> template <typename TFunc, typename... TT>
typename List<T>::Node* List<T>::find_prev_if(TFunc &&pred, TT&&... args)
{
    if (std::invoke(pred, args..., head->data))
        return nullptr;
................................................
Тогда
C++
1
lst.find_prev_if(std::equal_to<int>(), 123);
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2020, 19:28
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Нет, в функциях предикаты не делают параметром шаблона
Нет. Делают. И в функциях и в классах. В std::sort например. Но говорить в тоне Да/Нет/Не делают не хочу. Жалею что вмешался.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.09.2020, 19:32
Цитата Сообщение от IGPIGP Посмотреть сообщение
Нет. Делают. И в функциях и в классах. В std::sort например.
В std::sort сделано так же, как у меня
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2020, 19:47
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В std::sort сделано так же, как у меня
Так делают или нет?
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Нет, в функциях предикаты не делают параметром шаблона
и почему унарный? Будет вставлять перед чётными элементами?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.09.2020, 19:53
Цитата Сообщение от IGPIGP Посмотреть сообщение
Так делают или нет?
В классах предикат всегда параметр шаблона. В функциях - всегда обычный параметр.
Цитата Сообщение от IGPIGP Посмотреть сообщение
и почему унарный? Будет вставлять перед чётными элементами?
Я ж показал выше, как делаю обычно
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
emplate <typename T> template <typename TFunc, typename... TT>
typename List<T>::Node* List<T>::find_prev_if(TFunc &&pred, TT&&... args)
Где ты здесь видишь унарный?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.09.2020, 20:00
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В классах предикат всегда параметр шаблона. В функциях - всегда обычный параметр.
В функции std::sort - параметр шаблона:
https://en.cppreference.com/w/cpp/algorithm/sort
//третий вариант
C++
1
2
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Я ж показал выше, как делаю обычно
Но это же не значит, что всегда и все?
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Где ты здесь видишь унарный?
Они вызываются как унарные. Или нет?
Вот:
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Да, здесь ошибся
C++
1
2
if (pred(head->data))
 return nullptr;
и вот:
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
C++
1
while (current->ptrNext && !pred(current->ptrNext->data))
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
24.09.2020, 20:07
Цитата Сообщение от IGPIGP Посмотреть сообщение
В функции std::sort - параметр шаблона:
А у меня тогда какой, по-твоему?

Цитата Сообщение от IGPIGP Посмотреть сообщение
Они вызываются как унарные. Или нет?
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Другое дело, что я здесь слегка упростил. Обычно я делаю вот так
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
template <typename T>
template <typename TFunc, typename... TT>
typename List<T>::Node* List<T>::find_prev_if(TFunc &&pred, TT&&... args)
{
    if (std::invoke(pred, args..., head->data))
        return nullptr;
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Тогда
C++Выделить код
1
lst.find_prev_if(std::equal_to<int>(), 123);
Добавлено через 4 минуты
Параметр шаблона:
C++
1
2
3
4
template <int Val> func1() {}
func<123>();
template <typename T> func1() {}
func<int>();
Обычный параметр
C++
1
2
template <typename T> func2(T &&val) {}
func2(123);
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.09.2020, 20:07

Реализация односвязного списка
Добрый день.Уже как 2 недели разбираюсь с односвязным списком.Почти доделал до нужного состояния ,но по каким-то причинам я выхожу за...

Реализация односвязного списка c++
Пытаюсь разобраться в том как работают списки , но ничего не компилируется , помогите найти ошибку . template&lt;typename T&gt; ...

Нужна реализация односвязного списка
Народ спасайте! Возможно у кого-то есть реализация простого списка, или знает кто какую статью на эту тему, или книгу какую по АТД! У меня...

Реализация односвязного списка (конструктор)
Доброго времени суток. Вот реализую односвязный список, застрял на конструкторе который принимает два итератора: List(iterator b,...

Реализация односвязного списка через классы
Реализую односвязный список, но почему-то на перегрузке оператора индексирования вызывается ошибка в форме &quot;несоответствие в списке...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru