О стеке простыми словами — для студентов и просто начинающих

Привет, я студент второго курса технического университета. После пропуска нескольких пар программирования по состоянию здоровья, я столкнулся с непониманием таких тем, как «Стек» и «Очередь». Путем проб и ошибок, спустя несколько дней, до меня наконец дошло, что это такое и с чем это едят. Чтобы у вас понимание не заняло столько времени, в данной статье я расскажу о том что такое «Стек», каким образом и на каких примерах я понял что это такое. Если вам понравится, я напишу вторую часть, которая будет затрагивать уже такое понятие, как «Очередь»

Теория

На Википедии определение стека звучит так:

Стек (англ. stack — стопка; читается стэк) — абстрактный тип данных, представляющий собой список элементов, организованных по принципу LIFO (англ. last in — first out, «последним пришёл — первым вышел»).
Достаточно полное определение, но возможно для новичков оно будет немного трудным для понимания.

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


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

Итак, из чего же состоит стек.
Стек состоит из ячеек(в примере — это книги), которые представлены в виде структуры, содержащей какие-либо данные и указатель типа данной структуры на следующий элемент.
Сложно? Не беда, давайте разбираться.

На данной картинке схематично изображен стек. Блок вида «Данные/*next» и есть наша ячейка. *next, как мы видим, указывает на следующий элемент, другими словами указатель *next хранит адрес следующей ячейки. Указатель *TOP указывает на вершину стек, то есть хранит её адрес.

С теорией закончили, перейдем к практике.

Практика

Для начала нам нужно создать структуру, которая будет являться нашей «ячейкой»

Код на C++struct comp { //Структура с названием comp(от слова component) int Data; //Какие-то данные(могут быть любыми, к примеру можно написать int key; char Data; так-же можно добавить еще какие-либо данные) comp *next;//Указатель типа comp на следующий элемент };

Новичкам возможно будет не понятно, зачем наш указатель — типа comp, точнее сказать указатель типа структуры comp. Объясню, для того чтобы указатель *next мог хранить структуру comp, ей нужно обозначить тип этой структуры. Другими словами указать, что будет хранить указатель.

После того как у нас задана «Ячейка», перейдем к созданию функций.

Функции

Функция создания «Стека»/добавления элемента в «Стек»

При добавлении элемента у нас возникнет две ситуации:

  • Стек пуст, и нужно создать его
  • Стек уже есть и нужно лишь добавить в него новый элемент

Функцию я назову s_push, перейдем к коду.
Код на C++void s_push(comp **top, int D) { //функция типа void(ничего не возвращает) которая принимает указатль на вершину стека и переменную которая будет записываться в ячейку comp *q; //Создаем новый указатель q типа структуры comp. По сути это и есть наш новый элемент q = new comp(); //выделяем память для нового элемента q->Data = D; //Записываем необходимое число в Data элемента if (top == NULL) { //Если вершины нет, то есть стек пустой *top = q; //вершиной стека будет новый элемент } else //если стек не пустой { q->next = *top; //Проводим связь от нового элемента, к вершине. Тоесть кладем книжку на вершину стопки. *top = q; //Обозначаем, что вершиной теперь является новый элемент } }

Разберем чуть чуть по-подробнее.
Во-первых, почему функция принимает **top, то есть указатель на указатель, для того чтобы вам было наиболее понятно, я оставлю рассмотрение этого вопроса на потом. Во-вторых, по-подробнее поговорим о q->next = *top и о том, что же означает ->.

-> означает то, что грубо говоря, мы заходим в нашу структуру и достаем оттуда элемент этой структуры. В строчке q->next = *top мы из нашей ячейки достаем указатель на следующий элемент *next и заменяем его на указатель, который указывает на вершину стека *top. Другими словами мы проводим связь, от нового элемента к вершине стека. Тут ничего сложного, все как с книгами. Новую книгу мы кладем ровно на вершину стопки, то есть проводим связь от новой книги к вершине стопки книг. После этого новая книга автоматически становится вершиной, так как стек не стопка книг, нам нужно указать, что новый элемент — вершина, для этого пишется: *top = q;.

Функция удаления элемента из «Стека» по данным

Данная функция будет удалять элемент из стека, если число Data ячейки(q->Data) будет равна числу, которое мы сами обозначим.

Здесь могут быть такие варианты:

  • Ячейка, которую нам нужно удалить является вершиной стека
  • Ячейка, которую нам нужно удалить находится в конце, либо между двумя ячейками

Код на C++void s_delete_key(comp **top, int N) {//функция которая принимает вершину top и число которое нужно удалить comp *q = *top; //создаем указатель типа comp и приравниваем(ставим) его на вершину стека comp *prev = NULL;//создаем указатель на предыдуший элемент, с начала он будет пустым while (q != NULL) {//пока указатель q не пустой, мы будем выполнять код в цикле, если он все же пустой цикл заканчивается if (q->Data == N) {//если Data элемента равна числу, которое нам нужно удалить if (q == *top) {//если такой указатель равен вершине, то есть элемент, который нам нужно удалить — вершина *top = q->next;//передвигаем вершину на следующий элемент free(q);//очищаем ячейку q->Data = NULL; //Далее во избежание ошибок мы обнуляем переменные в удаленной ячейке, так как в некоторых компиляторах удаленная ячейка имеет переменные не NULL значения, а дословно «Чтение памяти невозможно» или числа «-2738568384» или другие, в зависимости от компилятора. q->next = NULL; } else//если элемент последний или находится между двумя другими элементами { prev->next = q->next;//Проводим связь от предыдущего элемента к следующему free(q);//очищаем ячейку q->Data = NULL;//обнуляем переменные q->next = NULL; } }// если Data элемента НЕ равна числу, которое нам нужно удалить prev = q; //запоминаем текущую ячейку как предыдущую q = q->next;//перемещаем указатель q на следующий элемент } }

Указатель q в данном случае играет такую же роль, что и указатель в блокноте, он бегает по всему стеку, пока не станет равным NULL(while(q != NULL)), другими словами, пока стек не закончится.

Для лучшего понимания удаления элемента проведем аналогии с уже привычной стопкой книг. Если нам нужно убрать книгу сверху, мы её убираем, а книга под ней становится верхней. Тут то же самое, только в начале мы должны определить, что следующий элемент станет вершиной *top = q->next; и только потом удалить элемент free(q);

Если книга, которую нужно убрать находится между двумя книгами или между книгой и столом, предыдущая книга ляжет на следующую или на стол. Как мы уже поняли, книга у нас-это ячейка, а стол получается это NULL, то есть следующего элемента нет. Получается так же как с книгами, мы обозначаем, что предыдущая ячейка будет связана с последующей prev->next = q->next;, стоит отметить что prev->next может равняться как ячейке, так и нулю, в случае если q->next = NULL, то есть ячейки нет(книга ляжет на стол), после этого мы очищаем ячейку free(q).
Так же стоит отметить, что если не провести данную связь, участок ячеек, который лежит после удаленной ячейки станет недоступным, так как потеряется та самая связь, которая соединяет одну ячейку с другой и данный участок просто затеряется в памяти

Функция вывода данных стека на экран

Самая простая функция:

Код на C++void s_print(comp *top) { //принимает указатель на вершину стека comp *q = top; //устанавливаем q на вершину while (q) { //пока q не пустой (while(q) эквивалентно while(q != NULL)) printf_s(«%i», q->Data);//выводим на экран данные ячейки стека q = q->next;//после того как вывели передвигаем q на следующий элемент(ячейку) } }

Здесь я думаю все понятно, хочу сказать лишь то, что q нужно воспринимать как бегунок, он бегает по всем ячейкам от вершины, куда мы его установили вначале: *q = top;, до последнего элемента.

Главная функция

Хорошо, основные функции по работе со стеком мы записали, вызываем.
Посмотрим код:

Код на C++void main() { comp *top = NULL; //в начале программы у нас нет очереди, соответственно вершины нет, даем ей значение NULL //Дальше начинаем добавлять цифры от 1 до 5 в наш стек s_push(&top, 1); s_push(&top, 2); s_push(&top, 3); s_push(&top, 4); s_push(&top, 5); //после выполнения функций в стеке у нас будет 54321 s_print(top);//выводим s_delete_key(&top, 4); //Затем удаляем 4, в стеке получается 5321 printf_s(«\n»);//переводим на новую строку s_print(top);//выводим system(«pause»);//ставим на паузу }

Вернемся к тому, почему же в функцию мы передавали указатель на указатель вершины. Дело в том, что если бы мы ввели в функцию только указатель на вершину, то «Стек» создавался и изменялся только внутри функции, в главной функции вершина бы как была, так и оставалась NULL. Передавая указатель на указатель мы изменяем вершину *top в главной функции. Получается если функция изменяет стек, нужно передавать в нее вершину указателем на указатель, так у нас было в функции s_push,s_delete_key. В функции s_print «Стек» не должен изменяться, поэтому мы передаем просто указатель на вершину.
Вместо цифр 1,2,3,4,5 можно так-же использовать переменные типа int.

Полный код программы:

Код на C++ #include <stdio.h>; #include <iostream>; struct comp { //Структура с именем comp int Data; //Кикие то данные(могут быть любими, к примеру можно написать int key; char Data; или добавить еще какие то данные) comp *next;//Указатель типа comp на следующий эелемент }; void s_push(comp **top, int D) { //функция типа void(ничего не возвращает) которая принимает указатль на вершину стека и переменную которая будет записываться в ячейку comp *q; //Создаем новый указатель q, который приравниваем к вершине стека. По сути это и есть наш новый элемент q = new comp(); //выделяем память для нового элемента q->Data = D; //Записываем D в Data элемента if (top == NULL) { //Если вершины нет, тоесть стек пустой *top = q; //вершиной стека будет новый элемент } else //если стек не пустой { q->next = *top; //Проводим связь от нового элемента, к вершине. Тоесть кладем книжку на вершину стопки. *top = q; //Пишем, что вершиной теперь является новый элемент } } void s_delete_key(comp **top, int N) {//функция которая принимает вершину top и число которое нужно удалить comp *q = *top; //создаем указатель типа comp и приравниваем(ставим) его на вершину стека comp *prev = NULL;//создаем указатель на предыдуший элемент, с начала он будет пустым while (q != NULL) {//пока указатель q не путой, мы его будем проверять, если он все же пусть цикл заканчивается if (q->Data == N) {//если Data элемента равна числу, которое нам нужно удалить if (q == *top) {//если такой указатель равен вершине, то есть элемент, который нам нужно удалить — вершина *top = q->next;//передвигаем вершину на следующий элемент free(q);//очищаем ячейку q->Data = NULL; //Далее во избежание ошибок мы обнуляем переменные в удаленной ячейке, так как в некоторых компиляторах удаленная ячейка имеет переменные не NULL значения, а дословно «Чение памяти невозможно» или числа «-2738568384» или других, в зависимости от компилятора. q->next = NULL; } else//если элемент последний или находится между двумя другими элементами { prev->next = q->next;//Проводим связь от предыдущего элемента к следующему free(q);//очищаем ячейку q->Data = NULL;//обнуляем переменные q->next = NULL; } }// если Data элемента НЕ равна числу, которое нам нужно удалить prev = q; //запоминаем текущую ячейку как предыдущую q = q->next;//перемещаем указатель q на следующий элемент } } void s_print(comp *top) { //принимает указатель на вершину стека comp *q = top; //устанавливаем q на вершину while (q) { //пока q не пустой (while(q) эквивалентно while(q != NULL)) printf_s(«%i», q->Data);//выводим на экран данные ячейки стека q = q->next;//после того как вывели передвигаем q на следующий элемент(ячейку) } } void main() { comp *top = NULL; //в начале программы у нас нет очереди, соответственно вершины нет, даем ей значение NULL //Дальше начинаем добавлять цифры от 1 до 5 в наш стек s_push(&top, 1); s_push(&top, 2); s_push(&top, 3); s_push(&top, 4); s_push(&top, 5); //после выполнения функций в стеке у нас будет 54321 s_print(top);//выводим s_delete_key(&top, 4); //Затем удаляем 4, в стеке получается 5321 printf_s(«\n»);//переводим на новую строку s_print(top);//выводим system(«pause»);//ставим на паузу }

Результат выполнения

54321
5321

Так как в стек элементы постоянно добавляются на вершину, выводиться элементы будут в обратном порядке

Стек

Теги: Стек, стек на си, реализация стека, стек на массиве, динамически растущий стек, стек на односвязном сиске

Стек – наверное, самая простая структура данных, которую мы будем изучать и которой будем постоянно пользоваться. Стек – это структура данных, в которой элементы поддерживают принцип LIFO (“Last in – first out”): последним зашёл – первым вышел. Или первым зашёл – последним вышел.

Стек позволяет хранить элементы и поддерживает, обычно, две базовые операции:

  • PUSH – кладёт элемент на вершину стека
  • POP – снимает элемент с вершины стека, перемещая вершину к следующему элементу

Также часто встречается операция PEEK, которая получает элемент на вершине стека, но не снимает его оттуда.

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

Пусть, например, у нас есть стек чисел. Выполним несколько команд. Изначально стек пуст. Вершина стека – указатель на первый элемент, никуда не указывает. В случае си она может быть равна NULL.

Push 3

Теперь стек состоит из одного элемента, числа 3. Вершина стека указывает на число 3.

Push 5

Стек состоит из двух элементов, 5 и 3, при этом вершина стека указывает на 5.

Push 7

Стек состоит из трёх элементов, вершина стека указывает на 7.

Pop

Вернёт значение 7, в стеке останется 5 и 3. Вершина будет указывать на следующий элемент – 5.

Pop

Вернёт 5, в стеке останется всего один элемент, 3, на который будет указывать вершина стека.

Pop

Вернёт 3, стек станет пуст.

Последовательное выполнение операций push 3, push 5, push 7, pop, pop, pop

Часто сравнивают стек со стопкой тарелок. Чтобы достать следующую тарелку, необходимо снять предыдущие. Вершина стека – это вершина стопки тарелок.

Когда мы будем работать со стеком, возможны две основные и часто встречающиеся ошибки:

  • 1. Stack Underflow: Попытка снять элемент с пустого стека
  • 2. Stack Overflow: Попытка положить новый элемент на стек, который не может больше расти (например, не хватает оперативной памяти)

Программная реализация

Рассмотрим три простые реализации стека:

  • 1) Стек фиксированного размера на массиве
  • 2) Динамически растущий стек на массиве
  • 3) Динамически растущий стек на односвязном списке

Стек фиксированного размера, построенный на массиве

Отличительная особенность – простота реализации и максимальная скорость выполнения. Такой стек может применяться в том, случае, когда его максимальный размер известен заранее или известно, что он мал.

Сначала определяем максимальный размер массива и тип данных, которые будут в нём храниться:

#define STACK_MAX_SIZE 20 typedef int T;

Теперь сама структура

typedef struct Stack_tag { T data; size_t size; } Stack_t;

Здесь переменная size – это количество элементов, и вместе с тем указатель на вершину стека. Вершина будет указывать на следующий элемент массива, в который будет занесено значение.

Кладём новый элемент на стек.

void push(Stack_t *stack, const T value) { stack->data = value; stack->size++; }

Единственная проблема – можно выйти за пределы массива. Поэтому всегда надо проверять, чтобы не было ошибки Stack overflow:

#define STACK_OVERFLOW -100 #define STACK_UNDERFLOW -101 void push(Stack_t *stack, const T value) { if (stack->size >= STACK_MAX_SIZE) { exit(STACK_OVERFLOW); } stack->data = value; stack->size++; }

Аналогично, определим операцию Pop, которая возвращает элемент с вершины и переходит к следующему

T pop(Stack_t *stack) { if (stack->size == 0) { exit(STACK_UNDERFLOW); } stack->size—; return stack->data; }

И функция peek, возвращающая текущий элемент с вершины

T peek(const Stack_t *stack) { if (stack->size <= 0) { exit(STACK_UNDERFLOW); } return stack->data; }

Ещё одно важное замечание – у нас нет функции создания стека, поэтому необходимо вручную обнулять значение size

Вспомогательные функции для печати элементов стека

void printStackValue(const T value) { printf(«%d», value); } void printStack(const Stack_t *stack, void (*printStackValue)(const T)) { int i; int len = stack->size — 1; printf(«stack %d > «, stack->size); for (i = 0; i < len; i++) { printStackValue(stack->data); printf(» | «); } if (stack->size != 0) { printStackValue(stack->data); } printf(«\n»); }

Заметьте, что в функции печати мы использует int, а не size_t, потому что значение len может стать отрицательным. Функция печатает сначала размер стека, а потом его содержимое, разделяя элементы символом |

Проверка

Stack_t stack; stack.size = 0; push(&stack, 3); printStack(&stack, printStackValue); push(&stack, 5); printStack(&stack, printStackValue); push(&stack, 7); printStack(&stack, printStackValue); printf(«%d\n», pop(&stack)); printStack(&stack, printStackValue); printf(«%d\n», pop(&stack)); printStack(&stack, printStackValue); printf(«%d\n», pop(&stack)); printStack(&stack, printStackValue); _getch();

Рассмотрим также ситуации, когда есть ошибки использования. Underflow

void main() { Stack_t stack; stack.size = 0; push(&stack, 3); pop(&stack); pop(&stack); _getch(); } void main() { Stack_t stack; size_t i; stack.size = 0; for (i = 0; i < 100; i++) { push(&stack, i); } _getch(); }

Динамически растущий стек на массиве

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

Стек будет состоять из указателя на данные, размера массива (максимального), и числа элементов в массиве. Это число также будет и указывать на вершину.

typedef struct Stack_tag { T *data; size_t size; size_t top; } Stack_t;

Для начала понадобится некоторый начальный размер массива, пусть он будет равен 10

#define INIT_SIZE 10

Алгоритм работы такой: мы проверяем, не превысило ли значение top значение size. Если значение превышено, то увеличиваем размер массива. Здесь возможно несколько вариантов того, как увеличивать массив. Можно прибавлять число, можно умножать на какое-то значение. Какой из вариантов лучше, зависит от специфики задачи. В нашем случае будем умножать размер на число MULTIPLIER

#define MULTIPLIER 2

Максимального размера задавать не будем. Программа будет выпадать при stack overflow или stack underflow. Будем реализовывать тот же интерфейс (pop, push, peek). Кроме того, так как массив динамический, сделаем некоторые вспомогательные функции, чтобы создавать стек, удалять его и чистить.

Во-первых, функции для создания и удаления стека и несколько ошибок

#define STACK_OVERFLOW -100 #define STACK_UNDERFLOW -101 #define OUT_OF_MEMORY -102 Stack_t* createStack() { Stack_t *out = NULL; out = malloc(sizeof(Stack_t)); if (out == NULL) { exit(OUT_OF_MEMORY); } out->size = INIT_SIZE; out->data = malloc(out->size * sizeof(T)); if (out->data == NULL) { free(out); exit(OUT_OF_MEMORY); } out->top = 0; return out; } void deleteStack(Stack_t **stack) { free((*stack)->data); free(*stack); *stack = NULL; }

Всё крайне просто и понятно, нет никаких подвохов. Создаём стек с начальной длиной и обнуляем значения.

Теперь напишем вспомогательную функцию изменения размера.

void resize(Stack_t *stack) { stack->size *= MULTIPLIER; stack->data = realloc(stack->data, stack->size * sizeof(T)); if (stack->data == NULL) { exit(STACK_OVERFLOW); } }

Здесь, заметим, в случае, если не удалось выделить достаточно памяти, будет произведён выход с STACK_OVERFLOW.

Функция push проверяет, вышли ли мы за пределы массива. Если да, то увеличиваем его размер

void push(Stack_t *stack, T value) { if (stack->top >= stack->size) { resize(stack); } stack->data = value; stack->top++; }

Функции pop и peek аналогичны тем, которые использовались для массива фиксированного размера

T pop(Stack_t *stack) { if (stack->top == 0) { exit(STACK_UNDERFLOW); } stack->top—; return stack->data; } T peek(const Stack_t *stack) { if (stack->top <= 0) { exit(STACK_UNDERFLOW); } return stack->data; }

Проверим

void main() { int i; Stack_t *s = createStack(); for (i = 0; i < 300; i++) { push(s, i); } for (i = 0; i < 300; i++) { printf(«%d «, peek(s)); printf(«%d «, pop(s)); } deleteStack(&s); _getch(); }

Напишем ещё одну функцию, implode, которая уменьшает массив до размера, равного числу элементов в массиве. Она может быть использована тогда, когда уже известно, что больше элементов вставлено не будет, и память может быть частично освобождена.

void implode(Stack_t *stack) { stack->size = stack->top; stack->data = realloc(stack->data, stack->size * sizeof(T)); }

Можем использовать в нашем случае

for (i = 0; i < 300; i++) { push(s, i); } implode(s); for (i = 0; i < 300; i++) { printf(«%d «, peek(s)); printf(«%d «, pop(s)); }

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

У неё есть недостаток, связанный с методом увеличения потребляемой памяти. При умножении в 2 раза (в нашем случае) требуется мало обращений к памяти, но при этом каждое последующее увеличение может привести к ошибке, особенно при маленьком количестве памяти в системе. Если же использовать более щадящий способ выделения памяти (например, каждый раз прибавлять по 10), то число обращений увеличится и скорость упадёт. На сегодня, проблем с размером памяти обычно нет, а менеджеры памяти и сборщики мусора (которых нет в си) работают быстро, так что агрессивное изменение преобладает (на примере, скажем, реализации всей стандартной библиотеки языка Java).

Реализация стека на односвязном списке

Что такое односвязный список, . Коротко: односвязный список состоит из узлов, каждый из которых содержит полезную информацию и ссылку на следующий узел. Последний узел ссылается на NULL.

Никакого максимального и минимального размеров у нас не будет (хотя в общем случае может быть). Каждый новый элемент создаётся заново. Для начала определим структуру узел

#define STACK_OVERFLOW -100 #define STACK_UNDERFLOW -101 #define OUT_OF_MEMORY -102 typedef int T; typedef struct Node_tag { T value; struct Node_tag *next; } Node_t;

Функция вставки первого элемента проста: создаём новый узел. Указатель next кидаем на старый узел. Далее указатель на вершину стека перекидываем на вновь созданный узел. Теперь вершина стека указывает на новый узел.

void push(Node_t **head, T value) { Node_t *tmp = malloc(sizeof(Node_t)); if (tmp == NULL) { exit(STACK_OVERFLOW); } tmp->next = *head; tmp->value = value; *head = tmp; }

Функция pop берёт первый элемент (тот, на который указывает вершина), перекидывает указатель на следующий элемент и возвращает первый. Здесь есть два варианта – можно вернуть узел или значение. Если вернём значение, то придётся удалять узел внутри функции

Node_t* pop1(Node_t **head) { Node_t *out; if ((*head) == NULL) { exit(STACK_UNDERFLOW); } out = *head; *head = (*head)->next; return out; }

и

T pop2(Node_t **head) { Node_t *out; T value; if (*head == NULL) { exit(STACK_UNDERFLOW); } out = *head; *head = (*head)->next; value = out->value; free(out); return value; }

Теперь вместо проверки на длину массива везде используется проверка на равенство NULL вершины стека.

Простая функция peek

T peek(const Node_t* head) { if (head == NULL) { exit(STACK_UNDERFLOW); } return head->value; }

Итерирование достаточно интересное. Просто переходим от одного узла к другому, пока не дойдём до конца

void printStack(const Node_t* head) { printf(«stack >»); while (head) { printf(«%d «, head->value); head = head->next; } }

И ещё одна проблема – теперь нельзя просто посмотреть размер стека. Нужно пройти от начала до конца и посчитать все элементы. Например, так

size_t getSize(const Node_t *head) { size_t size = 0; while (head) { size++; head = head->next; } return size; }

Конечно, можно хранить размер отдельно, можно обернуть стек со всеми данными ещё в одну структуру и т.д. Рассмотрим всё это при более подробном изучении списков.

Тестируем

Для лепки из глины однозначно понадобятся инструменты, некоторую часть из которых есть возможность изготовить самостоятельно. Стек — неотъемлемое дополнение руки мастера лепки из глины. На этом занятии мы стек для лепки своими руками.

Набор стеков можно приобрести в магазине, но из тех, что наиболее распространены — пластиковые — и вы не найдете ни одного удобного. Я не раз пробовал использовать фабричные стеки, но каждый раз был разочарован, так как приобретенный набор стеков — ненужные куски материала. Именно поэтому призываю вас изготовить для себя набор уникальных авторских стеков самостоятельно, ведь пока его готовишь — он уже и руке становится привычен.

Материал для стеков

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

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

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

Грубая обработка

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

Итак. Черенок я распилил на отрезки по пятнадцать сантиметров и расколол на несколько частей. Для нужного мне стека подошла плоская часть расколотого черенка.

Выстругать деревянный нож острым лезвием канцелярского ножа особого труда не стоит и уже через пару минут я имею грубую форму будущего стека для лепки. Одна его половина в виде лезвия шириной 15мм. и длиной около 10см., а другая в виде шила с острым концом, которое по совместительству служит рукоятью.

Шлифовка стека

Еще через пять минут у меня на столе лежал почти оформленный стек для лепки, осталось его только обработать абразивной бумагой — нождачкой. Быстре движения вдоль! волокон и стек постепенно теряет все неровности. Более мелкой нождачной можно придать форму приятную гладкую поверхность.

Вот и все — стек готов. Теперь им можно не только примазывать элементы, но и обрезать плоские детали и отсекать лишнее. Более подробно мы познакомимся с его функциями на других занятиях.

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

Лепка

Материалы для лепки

Для лепки применяются различные пластичные материалы: глина, пластилин, воск. Чем пластичнее материал, тем лучше работать.

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

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

Глина, применяемая для лепных работ, так называемая скульптурная глина, должна содержать наименьшее количество песка, чтобы иметь хорошую пластичность. Для получения пластичной глины тощую глину, то-есть глину, содержащую много песка, надо отмутить. Отмучивание глины производят так: в прочной посуде глину разводят до густоты сливок; 2/3 массы сливают в другую посуду. Через 10—12 часов глина осядет на дно, а вода поднимется наверх. Воду сливают, а глину вынимают и просушивают до тех пор, пока она не станет густой, как тесто. Из глиняного теста делают небольшие кирпичи, которые удобно хранить.

Вода для работы и приготовления материалов должна быть чистой — из колодца или водопровода. Болотная вода засорена органическими примесями, быстро загнивает и начинает издавать неприятный запах. Поэтому она не пригодна для работы.

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

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

От долгого хранения глина все же высыхает и требует размачивания. От этого недостатка избавлены пластилин и воск. Их можно купить в магазинах культтоваров.

Пластилин в основном применяют для лепки маленьких моделей. Он представляет собой искусственную пластическую массу, которая в отличие от глины очень долго не сохнет и, следовательно, всегда готова для лепки.

Пластилины бывают по своему составу простые и сложные, в зависимости от рецепта, по которому они приготовлены.

Мы приведем здесь лишь три рецепта наиболее простого приготовления пластилина.

Рецепт 1-й. Отмучивают глину и дают ей просохнуть до густоты теста. Затем в глиняное тесто льют глицерин и тщательно перемешивают его с глиной до однородной массы. Глицерин льют до тех пор, пока глиняная масса почти перестанет прилипать к рукам.

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

Рецепт 3-й. Отмученную сухую глину толкут в порошок и просеивают через частое сито. 1 часть толченой глины смешивают с 1/5 частью топленого воска, добавляя при этом в смесь несколько капель глицерина — столько, сколько нужно, чтобы пластилин был мягок и не приставал к рукам.

Пластилин тверже глины, и лепить из него следует только тогда, когда он хорошо размят в руках, сделается мягким. Кроме глины и пластилина, для лепки применяется воск.

Воск не сохнет, не требует смачивания водой, не дает трещин и сохраняется очень долго. Воск бывает естественный, изготовленный из вощины, и искусственный, изготовленный из нефти. Для лепки может применяться и тот и другой воск. Из воска лепят лишь мелкие изделия, так как он довольно дорого стоит.

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

Воск для лепки можно приготовить и самим. Самый доступный рецепт приготовления воска такой:

Берется:

воска — 1000 граммов,

свиного топленого сала — 65—70 граммов,

скипидара — 130—140 граммов,

сурика сухого железного или охры — 720—750 граммов.

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

Далее смесь перекладывают в ведро или в таз, наполненный водой комнатной температуры, и месят ее до тех пор, пока она не станет пластичной и не перестанет прилипать к рукам. Перемешанную смесь вынимают из воды и формуют в кирпичики.

Инструменты для лепки

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

Ножи необходимы лепщику для изготовления стеков, шаблонов, обрезания глины, формовки и т. д.

Стеки являются основным инструментом при лепке из глины, воска или пластилина. Они изготовляются из дерева твердых пород: бука, клена, березы, дуба, пальмы, сирени, иногда из ели, длиной от 10 до 25 сантиметров и толщиной в своей наиболее толстой части от 1 до 3 сантиметров. Концы стеков делаются самой разнообразной формы: плоской, треугольной, остроугольной, закругленной, круглой и т. д.

Рис. 225. Ножи и стеки:

1 — инструментальный нож и формовочный нож; 2 — деревянные стеки.

Рис. 226. Стеки с металлическими наконечниками.

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

При работе с пластилином и воском применяют часто металлические стеки, которые можно нагревать. Они изготовляются из толстой медной, алюминиевой или железной проволоки.

Циркуль. Основное назначение циркуля — вычерчивание рисунков и измерение моделей.

Циркуль-пантограф применяется для измерения при увеличении и уменьшении размеров лепимых изделий. Циркули-пантографы бывают металлические и деревянные. Они продаются в магазинах. Как самим сделать пантограф, рассказано на страницах 132—134 этой книги.

Мерник применяется для измерения высоты различных точек модели, выступающих над плоскостью фона. При лепке орнамента мерник является незаменимым инструментом, так как орнамент имеет весьма рельефную поверхность.

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

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

Кисти необходимы для обметания с изделий пыли, крошек глины, для промывки изделий, смазывания их смазкой.

Желательно иметь кисть диаметром 2—3 сантиметра и две-три кисти диаметром 1,5 сантиметра.

Спринцовка применяется для опрыскивания глиняных изделий водой и смывания глины во время формовки. Спринцовки продаются в аптеках и аптекарских магазинах.

Как сделать различные инструменты, необходимые для лепки, рассказывается далее.

Место для лепки и его оборудование

Лепить можно в любой светлой комнате или классе с равномерным освещением. Конечно, при этом следует соблюдать соответствующую чистоту и каждый раз убирать за собой рабочее место.

Летом хорошо лепить на воздухе — в тени под деревом или под временно устроенным навесом. Правда, глина на воздухе высыхает быстрее и требует поэтому более частого увлажнения.

Для хранения материалов, изделий и инструментов следует иметь кладовую или шкаф.

Лепить лучше всего на мольберте. Простой мольберт делают из досок на шпонках (чтобы не покоробило), к ним прибивают для упора две рейки. Можно сделать и более сложный мольберт, а также станок для лепки объемных изделий. Для мольберта прежде всего делают подставку высотой от 1,5 до 2,5 метра на трех или четырех ножках. На подставке сверлят отверстия на расстоянии 10 сантиметров друг от друга. В отверстия вставляют гвозди или деревянные клинья, на которых на нужной высоте устанавливают щит.

Рис. 227. Мольберт для лепки:

1 — подставка; 2 — подставка со щитом.

Рис. 228. Простой мольберт-подставка.

Станок для лепки делают высотой по грудь работающего. Он может быть также на трех или четырех ножках. Между ножками станка обычно делается полочка, куда кладут инструменты, необходимые при работе. На крышке станка устанавливается вращающаяся подставка.

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

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

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

Лучший свет, конечно, — дневной. Можно лепить и при искусственном свете — электрическом или ламповом, но он неравномерен, слабо освещает работу и утомляет зрение. При искусственном освещении лучше делать только черновую работу.

Рис. 229. Станок для лепки объемных моделей:

1 — станок на трех ножках; 2 — станок на четырех ножках.

А теперь поговорим об инструментах, которые нам понадобятся для лепки.
1. Руки. Самый важный инструмент это руки и пальцы. Они могут сделать все что угодно, все, что мы только захотим, и при желании могут заменить все остальные инструменты.
2. Доска для лепки. Чтобы удобнее было лепить, обязательно обзаведитесь доской для лепки. На ней очень удобно катать колбаски и шарики, разрезать что-нибудь. В принципе это все можно делать и на столе. Но доску можно легко помыть под струей воды и она опять станет как новая.
3. Ножик. Очень часто в лепке бывает необходимо сделать несколько одинаковых деталей, например лапок для зверей, лепесточков для цветочков, колесиков для машинок и т.д. Для начала необходимо сделать заготовки одинакового размера. И тут нам на помощь приходит ножик. Сначала можно скатать колбаску, а потом разрезать ножом на равные части. Подойдет даже пластмассовый нож. С помощью ножа пластилин режут, приминают, процарапывают, тыкают…
4. Скалка. Одним из важных элементов лепке это пластины. Для их изготовления Вам может понадобиться скалка. Скалки можно найти в детских кулинарных наборах, а можно просто заменить на что-нибудь круглое и твердое с ровной поверхностью, например, обыкновенной стеклянной бутылкой. Чтобы пластилин не прилипал к скалке и дощечке, на которой Вы будете раскатывать, скалку и дощечку можно смочить влажной тряпочкой. Пластилин катают так же как и тесто. Толщина пластины зависит от силы нажима и от того, сколько времени вы её катаете.
5. Спички. Несмотря на то, что пластилиновые детали хорошо липнут друг к другу, для обеспечения более прочного соединения между ними можно использовать спички или зубочистки. Например, когда надо приделать голову к туловищу.
6. Стеки. Для лепки вам также понадобятся стеки. Это такие пластмассовые ножи разной формы. Они обычно продаются вместе с любым набором пластилина или вместе с досками для лепки. Стеками можно резать приминать, тыкать,
7. Салфетки. Каким бы хорошим не был Ваш пластилин, его небольшие частички неизбежно прилипают к рукам, доске, ножам, стекам. Поэтому, чтобы держать все в чистоте, можно использовать салфетки или полотенца.
И вообще, не бойтесь экспериментировать. Для некоторых поделок, вам могут понадобиться бусинки, фольга, пустые пластиковые бутылки, коробочки, картон, веточки и прочее.
На мягком, послушном пластилине хорошо отпечатываются все предметы с рельефной поверхностью. Тут пригодятся красивые пуговицы с выпуклым рисунком, мешковина, трикотаж крупной вязки и тому подобное. Пригодится даже колпачек от ручки или фломастера. С помощью него можно оживить Ваши поделки добрыми улыбками. Поднесите колпачок к голове наклонно отпечатайте его, но не весь, а только половину, например как на картинке.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *