Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lucik_op.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
2.88 Mб
Скачать

Адаптеры queue

Класс queue предназначен для вставки элементов в конец базовой структуры данных и удаления элементов из ее начала. Адаптер queue реализуется с контейнерами list и deque (по умолчанию).

Наряду с общими для всех классов адаптеров операциями push, pop, empty и size в классе queue имеются операции front – получения ссылки на первый элемент очереди, back – ссылки на последний элемент очереди.

#include <iostream>

using std::cout;

using std::endl;

#include <queue>

// #include <list> для базового контейнера list

typedef int T;

main()

{ std::queue <T> och;

// std::queue <T, std::list<T> > lst; очередь на основе контейнера list

och.push(1); // занесение в очередь

och.push(2);

och.push(3);

int k=och.size(); // количество элементов в очереди

cout << "Очередь : ";

if(och.empty()) cout<<" пустая"; // проверка на пустоту очереди

else

{ for(int i=0;i<k;i++)

{ cout<<och.front()<<' '; // вывод значения первого элемента очереди

och.pop(); // удаление из очереди первого элемента

}

}

cout<<endl;

return 0;

}

Результат работы программы:

Очередь : 1 2 3

Инструкция

std::queue <T> och;

создает очередь для хранения в ней значений типа T. Очередь создается на основе контейнера deque по умолчанию. Функция front считывает значение первого элемента очереди, не удаляя его из нее. Для этого используется функция pop.

Адаптеры priority_queue

Класс priority_queue используется для вставки элементов в отсортированном порядке в базовую структуру данных и удаления элементов из ее начала. Адаптер priority_queue реализуется с контейнерами vector (по умолчанию) и deque.

Элементы в очередь с приоритетом заносятся в соответствии со своим значением. Это означает, что элемент с максимальным значением помещается в начало очереди и будет первым из нее удален, а с минимальным - в конец очереди. Это достигается с помощью метода, называемого сортировкой кучи. Сравнение элементов выполняется функцией-объектом less<Тип> или другой компораторной функцией.

Как и предыдущие адаптеры, priority_queue использует операции push, pop, empty, size, а также операцию top – получения ссылки на элемент с наивысшим приоритетом.

Пассивные и активные итераторы

Можно определять итерацию как часть объекта или создавать отдельные объекты, ответственные за итеративный опрос других структур. К достоинствам второго подхода относятся:

- наличие выделенного итератора классов, позволяющего одновременно проводить несколько просмотров одного и того же объекта;

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

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

Ниже приведен пример использования активного итератора.

// --------------- реализация aktiv_itr.h файла -------------

#include <iostream>

#include <vector>

#include <string>

using namespace std;

class Node

{ string name;

public:

Node(string s) : name(s) {}

Node() {}

string getName() const

{ return name;}

};

class NodeCollection

{ vector<Node> vec;

int index;

public:

NodeCollection() : index(0) {}

void addNode(Node);

Node getNode(int) const;

int getIndex() const; //возвращает индекс последнего элемента

};

class Iterator // интерфейс итератора

{

public:

virtual Node next() = 0;

virtual bool isDone() const = 0;

virtual ~Iterator() { }

};

class ActiveIterator : public Iterator // реализация итератора

{ NodeCollection collection;

int currentIndex; // текущий индекс

public:

ActiveIterator(const NodeCollection&);

Node next();

bool isDone() const;

virtual ~ActiveIterator() { }

};

// ---------------- реализация aktiv_itr.cpp файла ---------------

#include "aktiv_itr.h"

void NodeCollection::addNode(Node n)

{ vec.push_back(n);

index++;

}

Node NodeCollection::getNode(int i) const

{ return vec[i]; }

int NodeCollection::getIndex() const

{ return index; }

ActiveIterator::ActiveIterator(const NodeCollection& c)

{ collection = c;

currentIndex = 0; // отсчет элементов начинается с нуля

}

Node ActiveIterator::next()

{ return(collection.getNode(currentIndex++)); }

bool ActiveIterator::isDone() const

{ if(collection.getIndex() > currentIndex)

return false; // продолжение итерации

else

return true; // итерация завершена

}

main()

{ NodeCollection c;

c.addNode(Node("first"));

c.addNode(Node("second"));

c.addNode(Node("third"));

Iterator* pI = new ActiveIterator(c); //инициализируем итератор

Node n;

while(!pI->isDone())

{ n = pI->next();

cout << n.getName() << endl;

}

delete pI;

return 0;

}

Результат работы программы:

first

second

third

Каждому итератору ставится в соответствие определенный объект. Переход к следующему элементу последовательности выполняется функцией next(), возвращающей 0, если итерация завершена. Функция isDone() проверяет принадлежность текущего индекса допустимому диапазону и возвращает информацию о состоянии процесса (true - если итерация завершена, иначе false).

Конструктор класса ActiveIterator сначала устанавливает связь между итератором и конкретным объектом. Затем текущий индекс устанавливается равным 0.

Класс итератора – абстрактный класс с отложенной реализацией методов next и isDone. Конкретная реализация их передана классу производному от Iterator.

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

template <class Item>

class PassiveIterator

{public:

PassiveIterator(const Queue<Item>&);

~PassiveIterator();

int apply(int (*) (const Item&));

protected:

const Queue<Item>& queue

};

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]