Стек – это упорядоченная коллекция элементов, добавление нового или удаление существующего элемента которой всегда происходит только с одного из её концов. Элемент, добавленный последним, будет удалён в первую очередь, а элемент, добавленный первым, в последнюю. Такой принцип организации называется «последним вошел – первым вышел» (Last-In-First-Out или LIFO).
Очередь очень похожа на стек, но, в отличие от него, элементы кладутся и забираются с разных концов. Этот принцип называется «первым вошел – первым вышел» (First-In-First-Out или FIFO). Это работает как реальная очередь или конвейер, то есть, элемент, попавший в очередь первым, первым же её и покинет.
Теперь, когда мы выяснили основные понятия, приступим к реализации стека и очереди.
Стек, впрочем как и очередь, должен поддерживать следующие операции:
- push – добавить (положить) в конец стека новый элемент
- pop – извлечь из стека последний элемент
- top – узнать значение последнего элемента (не удаляя его)
- length – узнать количество элементов в стеке
- clear – очистить стек (удалить из него все элементы)
Реализовать стек и набор операций над ним в D можно следующим образом:
private
{
import std.range;
}
// стек для хранения данных
class Stack(T)
{
private:
T[] elements;
public:
// добавление элемента в конец
void push(T element)
{
elements ~= element;
}
// добавление ряда элементов
void push(T[] elementsArray)
{
elements ~= elementsArray;
}
// удалить один элемент
void pop()
{
--elements.length;
}
// количество элементов
size_t length() const @property
{
return elements.length;
}
// вершина стека
T top() const @property
{
return elements[$-1];
}
// содержимое стека
T[] content() @property
{
return elements;
}
// очистить стек
void clear()
{
elements.length = 0;
}
// стек пустой ?
bool empty() const @property
{
if (elements.length == 0)
{
return true;
}
else
{
return false;
}
}
}
Введя параметризацию и воспользовавшись наследованием от класса Stack, можно добиться того, что он приобретет фиксированный размер, а добавление нового элемента приведет к сдвигу всего стека. Таким способом мы получим очередь из стека.
Реализуем это:
// Очередь
class ShiftedStack(T, size_t M) : Stack!T
{
private:
T[M] emptyStack = T.init;
public:
this()
{
elements ~= emptyStack;
}
override
{
void push(T element)
{
elements ~= element;
elements = elements[1..$];
}
void push(T[] elementsArray)
{
if (!elements.empty)
{
elements ~= elementsArray;
elements = elements[0..M];
}
}
void pop()
{
if (!elements.empty)
{
super.pop();
elements ~= emptyStack;
elements = elements[0..M];
}
}
size_t length() const @property
{
return M;
}
void clear()
{
elements = emptyStack;
}
}
}