OBOWIĄZKOWE DO PRZESŁANIA: jedno zadanie
Kolejka to ADT, który pozwala zapisywać dane i następnie pobierać je w takiej kolejności, w jakiej je zapisano (ang. first in, first out, FIFO; pierwszy wchodzi, pierwszy wychodzi). Typowe operacje dla ADT QUEUE są następujące:
// https://en.cppreference.com/w/cpp/container/queue
// https://en.cppreference.com/w/cpp/container/deque
#include <queue>
// W STL std::queue jest zbudowana na bazie std::deque.
// Przykład użycia kolejki.
std::queue<int> Q; // domyślnie std::deque
assert( Q.empty() );
for (auto item : {1, 2, 3, 5, 7})
Q.push(item); // wstawienie do kolejki (na koniec)
assert( Q.front() == 1 ); // odczyt
assert( Q.back() == 7 ); // odczyt
assert( Q.size() == 5 );
Q.front() = 11; // zmiana na początku kolejki
Q.back() = 77; // zmiana na końcu kolejki
assert( Q.front() == 11 );
assert( Q.back() == 77 );
while(!Q.empty()) {
std::cout << Q.front() << std::endl; // odczyt
Q.pop(); // usuwa z kolejki (z początku) 11, 2, 3, 5, 77
}
// Interfejs kolejki.
template <typename T>
class MyQueue {
// zależne od implementacji
public:
MyQueue(); // default constructor
~MyQueue();
MyQueue(const MyQueue& other); // copy constructor
MyQueue(MyQueue&& other); // move constructor
MyQueue& operator=(const MyQueue& other); // copy assignment operator, return *this
MyQueue& operator=(MyQueue&& other); // move assignment operator, return *this
bool empty() const; // checks if the container has no elements
std::size_t size() const; // liczba elementów w kolejce
void push(const T& item); // dodanie na koniec, push_back(item)
void push(T&& item); // dodanie na koniec, push_back(std::move(item))
T& front(); // zwraca koniec, nie usuwa
T& back(); // zwraca koniec, nie usuwa
void pop(); // usuwa początek kolejki, pop_front()
void clear(); // czyszczenie listy z elementów
void display();
};
Przygotować implementację realizującą ADT QUEUE na bazie tablicy cyklicznej. Kolejne elementy będą wstawiane do tablicy cyklicznie, czyli po dojściu do końca tablicy będzie przejście do początku tablicy. Rozmiar tablicy jest o jeden większy niż maksymalna planowana liczba elementów w kolejce, po to aby rozróżnić sytuacje pustej i pełnej kolejki.
// myqueue.h
template <typename T>
class MyQueue {
T* tab;
std::size_t msize; // największa możliwa liczba elementów plus jeden
std::size_t head; // pierwszy do pobrania
std::size_t tail; // pierwsza wolna pozycja
public:
MyQueue(std::size_t s=10) : msize(s+1), head(0), tail(0) {
tab = new T[s+1];
assert( tab != nullptr );
} // default constructor
~MyQueue() { delete [] tab; }
MyQueue(const MyQueue& other); // copy constructor
MyQueue(MyQueue&& other); // move constructor
// UWAGA Po przeniesieniu other.msize = 1, other.head = other.tail = 0.
MyQueue& operator=(const MyQueue& other); // copy assignment operator, return *this
MyQueue& operator=(MyQueue&& other); // move assignment operator, return *this
// UWAGA Po przeniesieniu other.msize = 1, other.head = other.tail = 0.
bool empty() const { return head == tail; }
bool full() const { return (head + msize -1) % msize == tail; }
std::size_t size() const { return (tail - head + msize) % msize; }
std::size_t max_size() const { return msize-1; }
void push(const T& item); // dodanie na koniec
void push(T&& item); // dodanie na koniec
T& front() { return tab[head]; } // zwraca początek
T& back() { return tab[(tail + msize -1) % msize]; } // zwraca koniec
void pop(); // usuwa początek
void clear(); // czyszczenie listy z elementów
void display();
};
Przygotować implementację realizującą ADT QUEUE na bazie listy powiązanej pojedynczo. Wykorzystać klasę SingleList [push_back(), pop_front()] lub std::forward_list [tu jest trudniej, bo nie ma back() i push_back()].
Przygotować implementację realizującą ADT QUEUE na bazie listy powiązanej podwójnie. Wykorzystać klasę DoubleList lub std::list. Możliwe są dwa warianty realizacji push() i pop(): (a) push_back() i pop_front(), (b) push_front() i pop_back().
Przygotować implementację realizującą ADT QUEUE na bazie dwóch stosów. Wykorzystać std::stack lub MyStack z zestawu nr 7.