Мы катим мир, а все остальные сидят внутри и кричат "А-а-а! Куда катится этот мир?!"
Господа сообщники, я прошу вашей помощи.
Необходимо реализовать очередь, а затем превратить ее в дэк, использовать при этом итераторы. Есть начальный код, который необходимо дописать. Я не понимаю ни принципов работы с итераторами, ни применения их к дэку, реализовать тоже толком ничего не могу.
Листание форумов и лекций пользы не принесло.
Подскажите, что делать, с чего начинать?
Необходимо реализовать очередь, а затем превратить ее в дэк, использовать при этом итераторы. Есть начальный код, который необходимо дописать. Я не понимаю ни принципов работы с итераторами, ни применения их к дэку, реализовать тоже толком ничего не могу.
Листание форумов и лекций пользы не принесло.
Подскажите, что делать, с чего начинать?
А что конкретно не понятно или не получается?
Если надо самому изобрести двусвязный список, то можно создать объект, в котором будут методы: инициализировать, добавить в начало, добавить в конец, взять с начала, взять с конца, проверить на наличие, разрушить. А по элементам этого списка ходить с помощью итераторов, а не индексированием массивов.
Если я правильно понял задачу, конечно.
и зачем.Для этого можно создать некоторый узел Node, а затем цеплять их друг к другу:
Тогда для создания списка придётся делать вот такое безобразие:
Не очень-то удобно. Можно добавить метод void Node::insert(TYPE data);, который будет добавлять элементы сам, а код будет прозрачен и чист. Для удобства можно ещё добавить конструктор Node::Node();, который уберёт кашу из памяти.
Дек это очередь. Очередь – это самостоятельный объект из узлов, которые в ней находятся. Посему создадим класс Queue, который будет иметь методы для работы с односвязным списком, а так же методы для дека.
В конечном итоге, выглядеть они могут приблизительно так:
Использовать можно примерно так:
Итераторы нужны для инкапсуляции. Из неё вытекают следующие бонусы:
– при обращении к элементу коллекции совершенно не нужно знать что из себя эта коллекция представляет (массив, вектор, список, дерево, набор и т.д.) – мы всё-равно можем использовать единый интерфейс для работы с ними.
– можно добавить дополнительный функционал, например, метод для проверки все элементы обошли или ещё есть необработанные, или после прохода элемента совершать над ним какие-нибудь действия.
– итераторы позволяют гибко обрабатывать попытки выйти за границы коллекции.
Итератор – отдельный объект. К чему его применять – для кода, который его использует – не важно, реализация работы с коллекцией описана внутри итератора. В самом простом случае, он должен содержать методы для перехода в начало/конец, для доступа к значению и для проверки на пустоту элемента (чтобы знать когда конец):
Использовать всё вместе с итератором можно примерно вот так:
Ещё было бы хорошо работать с добавлением/удалением элементов, передавая итератор по ссылке, а не напрямую как в примере выше: Queue::Insert(Iter&, TYPE) и Queue:
Общая схема очередей на односвязных списках примерно такова.
Тебе же нужно реализовать все описанные методы классов так, чтобы этот код корректно отработал (:
ps: следует заметить, что это задание, скорее всего, нужно в обучающих целях чтобы было понимание общих алгоритмов работы. На практике свой велосипед лучше не изобретать и использовать std::deque и std::iterator.
1. Одного типа можно сравнивать так же, как указатели – если указывают на один и тот же адрес, значит, то, на что они указывают – равно между собой.
2. Разных типов – не нужно сравнивать. Если это стало необходимо, значит, где-то проблема с логикой, а не с итераторами. В стандартах этого тоже нет до c++11 точно (насчёт последнего не уверен, не следил).
Вот общий пример того, как выглядит код обхода любой итерируемой коллекции из STL, если нужно сравнение в условии цикла:
Посмотрите на формулировки методов begin(), end() и работу с коллекцией smth – код (в данном случае цикл), работающий с ней, не знает в каком типе хранятся данные и ему это не нужно. В качестве коллекции может быть любой итерируемый тип данных (array, list, stack, queue, deque, set, map, vector и т.д.), а код для его обхода будет один и тот же.
ps: чтобы обойтись без перегрузки операторов и сделать код более читабельным, я в комменте выше использовал next() вместо ++ и get() вместо разыменовывания, но это одно и то же и суть не меняется.