Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на языке высокого уровня Паскаль. Учебное пособие для СПО

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
последующий по отношению к удаляемому элементы.
Сначала указатель p устанавливается на начало списка, и организуется цикл просмотра списка (оператор 1). Если поле данных очередного элемента совпало с заданным ключом (оператор 2), формируется признак успешного поиска и функция завершается. В противном случае перед переносом указателя на следующий элемент списка (он хранится в поле p текущего элемента, оператор 4) его значение запоминается в переменной pp (оператор 3) для того, чтобы при следующем проходе цикла в ней находился указатель на предыдущий элемент.
Если элемента с заданным ключом в списке нет, цикл завершится естественным образом, поскольку последний элемент списка содержит
nil в поле p указателя на следующий элемент.
Вставка элемента выполняется после элемента с заданным ключом (процедура insert ). Если с помощью функции find место вставки определить не удалось, выводится сообщение и процедура завершается (в этом случае можно было использовать и другой алгоритм — добавлять элемент к концу списка, это определяется конкретным предназначением программы). Если элемент найден, указатель на него заносится в переменную pkey.
Под новый элемент выделяется место в динамической памяти (оператор
1), и информационные поля элемента заполняются переданными в процедуру значениями (оператор 2). Новый элемент p вставляется между элементами pkey и следующим за ним (его адрес хранится в
pkey^.p ). Для этого в операторах 3 и 4 устанавливаются две связи
(рис. 5.4).
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
111
Рис. 5.4. Вставка элемента в список
Удаление элемента выполняет процедура del. В ней две ветви, поскольку при удалении элемента из начала списка изменяется указатель на начало, а при удалении второго и последующих элементов требуется связывать предыдущий и последующий по отношению к удаляемому элементы.
Бинарные деревья
Бинарное дерево — это динамическая структура данных, состоящая из узлов, каждый из которых содержит кроме данных не более двух ссылок на различные бинарные деревья. На каждый узел имеется ровно одна ссылка. Начальный узел называется корнем дерева.
Пример бинарного дерева приведен на рис. 5.5 (корень обычно изображается сверху). Узел, не имеющий поддеревьев, называется листом. Исходящие узлы называются предками, входящие — потомками. Высота дерева определяется количеством уровней, на которых располагаются его узлы.
Рис. 5.5. Пример бинарного дерева
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
112
Если дерево организовано таким образом, что для каждого узла все ключи его левого поддерева меньше ключа этого узла, а все ключи его правого поддерева — больше, оно называется деревом поиска. Одинаковые ключи не допускаются. В дереве поиска можно найти элемент, двигаясь от корня и переходя на левое или правое поддерево в зависимости от значения ключа в каждом узле. Такой поиск гораздо эффективнее поиска по списку, поскольку время поиска определяется высотой дерева, а она пропорциональна двоичному логарифму количества узлов.
Дерево является рекурсивной структурой данных, поскольку каждое поддерево также является деревом. Действия с такими структурами изящнее всего описываются с помощью рекурсивных алгоритмов. Например, процедуру обхода всех узлов дерева можно в общем виде описать так:
procedure print_tree( дерево ); begin print_tree( левое_поддерево ) посещение корня print_tree( правое_поддерево ) end;
Эта процедура позволяет получить последовательность ключей, отсортированную по возрастанию. Результат обхода дерева, изображенного на рис. 5.5:
1, 6, 8, 10, 20, 21, 25, 30
Если в функции обхода первое обращение идет к правому поддереву, результат обхода будет другим:
30, 25, 21, 20, 10, 8, 6, 1
Таким образом, деревья поиска можно применять для сортировки значений. При обходе дерева узлы не удаляются.
Для бинарных деревьев определены операции:
1. включения узла в дерево;
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
113
2. поиска по дереву;
3. обхода дерева;
4. удаления узла.
Для простоты будем рассматривать дерево, каждый элемент которого содержит только целочисленный ключ и два указателя.
type pnode = ^node; node = record data : word; { ключ } left : pnode; { указатель на левое поддерево } right : pnode { указатель на правое поддерево } end;
Доступ к дереву в программе осуществляется через указатель на его корень:
var root : pnode;
Рассмотрим сначала функцию поиска по дереву, так как она используется и при включении, и при удалении элемента (пример 5.4).
function find(root : pnode; key : word; var p, parent : pnode) : boolean; begin p := root; { поиск начинается от корня } while p <> nil do begin if key = p^.data then { узел с таким ключом есть } begin find := true; exit end; parent := p; { запомнить указатель перед спуском } if key < p^.data then p := p^.left { спуститься влево } else p := p^.right; { спуститься вправо } end; find := false; end;
Листинг 5.4. Функция поиска по бинарному дереву
Функция возвращает булевский признак успешности поиска. Ей передаются указатель на корень дерева, в котором выполняется поиск (
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
114
root ), и искомый ключ ( key ). Выходными параметрами функции
являются указатели на найденный элемент ( p ) и его предка ( parent ).
Удаление элемента — более сложная задача, поскольку при этом необходимо сохранить свойства дерева поиска. Эта задача подробно описана в учебнике [10].
В пример 5.5 приведен пример программы работы с бинарным деревом.
program bintree; uses crt; type pnode = ^node; node = record data : word; { ключ } left : pnode; { указатель на левое поддерево } right : pnode { указатель на правое поддерево } end; var root : pnode; key : word; option : word; { ------------------------------------ вывод дерева --------------------------- } procedure print_tree(p : pnode; level : integer); var i : integer; begin if p = nil then exit; with p^ do begin print_tree(right, level + 1); for i := 1 to level do write(' '); writeln(data); print_tree(left, level + 1); end end; { ------------------------------- поиск по дереву – см. рис. 5.5----------- } function find(root : pnode; key : word; var p, parent : pnode) : boolean; { ---------------------------- включение в дерево ----------------------------- } procedure insert(var root : pnode; key : word); var p, parent : pnode;
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
115
begin if find(root, key, p, parent) then begin writeln(' такой элемент уже есть'); exit; end; new(p); { создание нового элемента } p^.data := key; p^.left := nil; p^.right := nil; if root = nil then root := p { первый элемент } else { присоединение нового элемента к дереву} if key < parent^.data then parent^.left := p else parent^.right := p; end; { ------------------------------ удаление из дерева - см. учебник --------- } procedure del(var root : pnode; key : word); { ------------------------------- главная программа --------------------------- } begin root := nil; while true do begin writeln('1 - вставка, 2 - удаление, 3 - вывод, 4 - выход'); readln(option); case option of 1: begin { вставка } writeln('Введите ключ для вставки: '); readln(key); insert(root, key); end; 2: begin { удаление } writeln('Введите ключ для удаления: '); readln(key); del(root, key); end; 3: begin { вывод } clrscr; if root = nil then writeln ('дерево пустое') else print_tree(root, 0); end; 4: exit; { выход } end; writeln; end
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
116
end.
Листинг 5.5. Использование бинарного дерева
Рассмотрим функцию обхода дерева print_tree. Вторым параметром в нее передается целая переменная, определяющая, на каком уровне находится узел. Корень находится на уровне 0. Дерево печатается по горизонтали так, что корень находится слева. Для дерева, изображенного на рис. 5.5, вывод выглядит так:
30 25 21 20 10 8 6 1
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
117
Введение в объектно-ориентированное программирование
Основные свойства, достоинства и недостатки объектно­ориентированного подхода. Описание и использование объектов. Экземпляры объектов. Описание полей и методов. Директивы public и private.
Презентацию к данной работе Вы можете скачать здесь скачать: http://old.intuit.ru/department/pl/prinpas/6/Pascal_6.zip.
Объектно-ориентированное программирование (ООП) представляет собой дальнейшее развитие идей структурного программирования, основной целью которого является создание программ простой структуры. Это достигается за счет разбиения программы на максимально обособленные части.
Структурная программа состоит из совокупности подпрограмм, связанных с помощью интерфейсов. Подпрограмма работает с данными, которые либо являются локальными, либо передаются ей в качестве параметров. Каждая подпрограмма предназначена для работы с определенными типами данных. Ошибки часто связаны с тем, что в подпрограмму передаются неверные данные. Естественный путь избежать таких ошибок — связать в одно целое данные и все подпрограммы, которые предназначены для их обработки. Эта идея лежит в основе ООП: из предметной области выделяются объекты, поведение и взаимодействие которых моделируются с помощью программы.
Принципы ООП проще всего понять на примере программ моделирования. В реальном мире каждый предмет или процесс обладает набором статических и динамических характеристик, иными словами, свойствами и поведением. Поведение объекта зависит от его состояния и внешних воздействий. Например, если в объекте "автомобиль" повернуть руль, изменится положение колес, а если в баке нет бензина, автомобиль никуда не поедет.
Понятие объекта в программе совпадает с обыденным смыслом этого слова: объект представляется как совокупность данных,
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
118
характеризующих его состояние, и процедур их обработки, моделирующих его поведение. Вызов процедуры часто называют посылкой сообщения объекту.
При создании объектно-ориентированной программы предметная область представляется не в виде данных и обрабатывающих эти данные подпрограмм, как при процедурном подходе, а в виде совокупности объектов. Выполнение программы состоит в том, что объекты обмениваются сообщениями. Это позволяет использовать при программировании понятия, более адекватно отражающие предметную область.
При представлении реального объекта с помощью программного необходимо выделить в первом его существенные особенности. Их список зависит от цели моделирования. Например, объект "крыса" с точки зрения ветеринара, дачника или, скажем, повара будет иметь совершенно разные характеристики. Выделение существенных с точки зрения рассмотрения свойств называется абстрагированием. Таким образом, программный объект — это абстракция.
Важным свойством объекта является его обособленность. Чтобы пользоваться подпрограммой, достаточно знать только ее заголовок (интерфейс); объект тоже используется только через интерфейс — обычно это совокупность интерфейсов его подпрограмм. Детали реализации объекта, то есть внутренние структуры данных и алгоритмы их обработки, скрыты от пользователя и недоступны для непреднамеренных изменений.
Скрытие деталей реализации называется инкапсуляцией (от слова "капсула"). Ничего сложного в этом понятии нет: ведь и в обычной жизни мы пользуемся объектами через их интерфейсы. Сколько информации пришлось бы держать в голове, если бы для просмотра новостей надо было знать устройство телевизора!
Таким образом, объект является "черным ящиком", закрытым по отношению к внешнему миру. Это позволяет представить программу в более укрупненном виде — на уровне объектов и их взаимосвязей, а следовательно, управлять большим объемом информации и успешно отлаживать более сложные программы.
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
119
Сказанное выше можно сформулировать более кратко и строго: объект — это инкапсулированная абстракция с четко определенным интерфейсом.
Инкапсуляция позволяет изменить реализацию объекта без модификации основной части программы, если его интерфейс остался прежним (например, при необходимости изменить способ хранения данных с массива на стек). Простота модификации, как уже отмечалось, является важным критерием качества программы.
Кроме того, инкапсуляция позволяет использовать объект в другом окружении и быть уверенным, что он не испортит не принадлежащие ему области памяти, а также создавать библиотеки объектов для применения во многих программах.
Каждый год в мире пишется огромное количество новых программ, и важнейшее значение приобретает возможность повторного использования кода. Для структурных программ она сильно ограничена: любую подпрограмму либо можно использовать без изменений, либо надо переписывать. Преимущество объектно-ориентированного программирования состоит в том, что для любого объекта можно определить наследников, корректирующих или дополняющих его поведение. При этом нет необходимости иметь доступ к исходному коду родительского объекта.
Наследование позволяет создавать иерархии объектов.Иерархия представляется в виде дерева, в котором более общие объекты располагаются ближе к корню, а более специализированные — на ветвях и листьях. Наследование облегчает использование библиотек объектов, поскольку программист может взять за основу объекты из библиотеки и создать их наследников с требуемыми свойствами. В Паскале любой объект может иметь одного предка и произвольное количество потомков.
Применение ООП позволяет писать гибкие, расширяемые, хорошо читаемые программы. Во многом это обеспечивается благодаря полиморфизму, под которым понимается возможность во время выполнения программы с помощью одного и того же имени выполнять разные действия или обращаться к объектам разного типа. Чаще всего понятие полиморфизма связывают с механизмом виртуальных методов.
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
120
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]