Теоретический материал: стеки, очереди, кольца (Паскаль)
Сайт: | Информатикс |
Курс: | Структуры данных |
Книга: | Теоретический материал: стеки, очереди, кольца (Паскаль) |
Напечатано:: | Гость |
Дата: | Пятница, 27 Июнь 2025, 17:59 |
Стек. Отличия стека от списка. Основные операции со стеком
Сейчас Вы познакомитесь с одной из разновидностей обычного линейного списка – стеком. Этот вид списка очень часто используется в программировании.
Стек – это линейный список, в котором добавление новых элементов и удаление существующих производится только с одного конца, называемого вершиной стека.
Стек часто называют структурой LIFO (сокращение LIFO означает Last In – First Out, т.е. последним пришел – первым вышел). Это сокращение помогает запомнить механизм работы стека.
Изобразим стек графически:
При программировании на Паскале стек чаще всего реализуется в виде однонаправленного списка. Каждый элемент структуры содержит указатель на следующий. Однако, к этому виду списка, по определению, неприменима операция обхода элементов. Доступ возможен только к верхнему элементу структуры.
Стек предполагает вставку и удаление элементов, поэтому он является динамической, постоянно меняющейся структурой.
Стеки довольно часто встречаются в практической жизни. Простой пример: детская пирамидка. Процесс ее сборки и разборки подобен процессу функционирования стека.
Итак, стек – это такой список, добавление или извлечение элементов которого происходит с начала и только с начала (или, возможно, с конца и только с конца) списка.
Значением указателя, представляющего стек, является ссылка на вершину стека, и каждый элемент стека содержит поле ссылки на соседний, "нижний" элемент.
Таким образом, описать стек можно следующим образом:
Type
|
Если стек пуст, то значение указателя равно Nil.
Рассмотрим возможные операции со стеком.
Занесение элемента в стек
Занесение элемента в стек производится аналогично вставке нового элемента в начало списка. Процедура занесения элемента в стек должна содержать два параметра: первый задает вершину стека, в который нужно занести элемент, второй – заносимое значение элемента стека.
Процедура формирования стека будет иметь следующий вид:
Procedure FormStack;
|
Извлечение элемента из стека
В результате выполнения этой операции некоторой переменной i должно быть присвоено значение первого элемента стека, и значение указателя на начало списка должно быть перенесено на следующий элемент стека.
Procedure readStack(Var u : EXST; Var i : integer);
|
Недостатком описанной процедуры является предположение о том, что стек не пуст. Для его исправления следует разработать логическую функцию, определяющую, пуст ли обрабатываемый стек.
Function FreeStack(u : EXST) : boolean;
|
Задание. Описать функцию и закончить программу, для чего описать процедуру вывода значений элементов стека на экран (она аналогична выводу списка). Протестировать программу, дополнить комментарием.
Примеры решения задач
Пример 1. Используя стек, напечатать содержимое текстового файла, выписывая литеры каждой его строки в обратном порядке.
Program MordovskihK;
|
Пример 2. Написать программу, проверяющую своевременность закрытия скобок в строке символов.
Для решения задачи определим стек, элементами которого являются символы:
Type
|
Будем двигаться по строке а : string до ее конца. Если в процессе просмотра встретится одна из открывающих скобок ({, (, [ ), занесем ее в стек. При обнаружении закрывающей скобки, соответствующей скобке, находящейся в вершине стека, последняя удаляется. При несоответствии скобок выдается сообщение об ошибке.
Пусть факт наличия ошибки хранится в переменной логического типа f, то есть f=True, пока ошибка не найдена и f=False в противном случае. Тогда условие работы цикла будет выглядеть так:
while (i<>Length(a)) and f do ...
|
Осталось выяснить, как определить, соответствует ли очередная закрывающая скобка скобке, находящейся в вершине стека. Можно заметить, что коды соответствующих друг другу скобок отличаются не более чем на 2, что можно проверить с помощью функции Ord(x)):
{ } 123–125
|
причем код открывающей скобки меньше. Таким образом, можно записать следующее условие соответствия:
if (Ord(a[i])–Ord(stack^.Data))<=2
|
А теперь просмотрите полный текст программы:
Program Skobki;
|
Задание. Разберите алгоритмы решения предложенных задач.
Очередь. Основные операции над очередью
Очередь – линейный список, элементы в который добавляются только в конец, а исключаются из начала.
Изобразим очередь графически:
Итак, очередь – это вид связанного списка, в котором извлечение элементов происходит с начала списка, а добавление новых элементов – с конца. К этому виду списка, по определению, неприменима операция обхода элементов.
Очередь является динамической структурой – с течением времени изменяется и колчество, и набор составляющих ее элементов.
Опишем очередь на языке программирования:
Type
|
Над очередью определены две операции: занесение элемента в очередь и извлечение элемента из очереди.
В очереди, в силу ее определения, доступны две позиции: ее конец, куда заносятся новые элементы, и ее начало, откуда извлекаются элементы. Поэтому для работы с очередью необходимо описать две переменные:
Var
|
где BeginO – соответствует началу очереди и будет использоваться для удаления элемента из очереди, EndO – соответствует концу очереди и будет использоваться для добавления новых элементов в очередь.
Занесение элемента в очередь
Занесение элемента в очередь реализуется как добавлению элемента в конец списка. Рассмотрите процедуру, описанную ниже.
Procedure writeO(Var BeginO, EndO : EXO; c : integer);
|
Задание. Создайте программу формирования очереди с использованием предложенной процедуры.
Извлечение элемента из очереди
Процедура извлечения элемента из очереди аналогична удалению элемента из начала списка. Поскольку извлечение элемента из пустой очереди осуществить нельзя, опишем логическую функцию, проверяющую, есть ли элементы в очереди.
Procedure readO(Var BeginO : EXO; Var c : integer);
|
Задание. Напишите программу, содержащую все необходимые процедуры и функции работы с очередью.
Примеры решения задач
Задание. Рассмотрите приведенные программы. Наберите их на компьютере, дополните комментарием и протестируйте. Имейте в виду, что уже рассмотренные выше подпрограммы в текстах задач пропущены.
Пример 1. За один просмотр файла действительных чисел напечатать элементы файла в следующем порядке: сначала – все числа, меньшие а, затем – все числа из отрезка [а, b], и наконец – все остальные числа, сохраняя исходный порядок в каждой из этих трех групп чисел. Числа а и b задает пользователь.
Program MordovskihK;
|
Пример 2. Из заданного текста перенести все цифры в конец каждой строки, сохранив их порядок.
Program BaranovA;
|
Кольцо. Формирование кольца. Основные операции над кольцом
Koльцо - это вид связанного списка, в котором указатель последнего элемента ссылается на первый элемент.
Рассмотрите его графическое представление.
К кольцу применим обход элементов, доступ возможен к любому элементу структуры.
Кольцо является динамической структурой – может изменяется и количество, и набор составляющих его элементов.
Опишем кольцо на языке программирования:
Type
|
Формирование кольца
Рассмотрите процедуру формирования кольца. Для работы этой процедуры заводятся две локальные переменные типа TypeCircle для хранения адресов промежуточного и завершающего звена списка, последним оператором преобразуемого в кольцо.
Procedure FofmK(Var u : TypeCircle);
|
Над кольцом определены три операции: занесение элемента в кольцо, извлечение элемента из кольца и обход кольца.
Задание. Составьте программу, содержащую две процедуры: процедуру занесения элемента в кольцо и процедуру извлечения элемента из кольца по какому-либо условию. (Можно воспользоваться текстом предыдущей программы.)
Обход кольца
Для того чтобы обойти кольцо и вывести на экран содержащуюся в нем информацию, необходимо в локальной переменной типа TypeCircle запомнить адрес первого выводимого элемента. В этом случае можно избежать повторения и зацикливания программы. Вывод данных можно начинать с любого элемента кольца; это зависит от адреса первого элемента, переданного в процедуру обхода.
Рассмотрите процедуру обхода кольца.
Procedure PrintК(u : TypeCircle);
|
Задание. Составьте программу, использующую процедуры формирования и обхода кольца, дополните ее процедурой освобождения динамической памяти, выделенной для хранения кольца.
Решение задач с применением динамической структуры кольцо
Задание/b>>/>. Рассмотрите приведенную программу, наберите ее на компьютере, вставьте комментарий.
Задача 1. N ребят располагаются по кругу. Начав отсчет от первого, удаляют каждого k-го, смыкая при этом круг. Определить порядок удаления ребят из круга.
Program Schitalka;
|