- •64 Жегуло а.И. Компьютерные науки 2-й семестр 2011-2012 гг. Компьютерные науки Лекции для студентов 1 курса мехмата, 2011-2012 уч. Г.
- •2 Семестр
- •16.Модули
- •16.1.Модуль и модульное программирование
- •16.2.Структура модуля
- •Interface //Раздел интерфейса
- •Implementation //Раздел реализации
- •Initialization //Раздел инициализации
- •Пример модуля и его использования
- •Interface //Раздел интерфейса
- •Implementation //Раздел реализации
- •Заголовок модуля
- •Раздел интерфейса interface
- •Раздел реализации implementation
- •Раздел инициализации initialization
- •16.4.Использование объявленных в модуле объектов
- •17.Файлы
- •17.1.Файлы. Классификация файлов
- •17.2.Организация работы с файлами
- •17.3.Подпрограммы для работы с файлами любых типов Связывание файловой переменной с файлом
- •Запись в файл
- •17.5.Обработка ошибок ввода-вывода
- •17.6.Текстовые файлы
- •17.6.1.Структура текстового файла
- •17.6.2.Особенности открытия текстовых файлов
- •17.6.3.Особенности чтения и записи для текстовых файлов
- •17.6.7.Поэлементная обработка текстовых файлов, состоящих из строковых значений и чисел
- •17.7.Типизированные файлы
- •17.7.1.Описание и структура типизированного файла
- •17.7.5.Сравнение текстовых и типизированных файлов
- •17.7.6.Пример работы с типизированными файлами из записей
- •18.Процедурные типы
- •18.1.Назначение процедурных типов
- •18.2.Описание процедурных типов и процедурных переменных
- •18.3.Присваивание процедурным переменным. Вызов подпрограмм через процедурные переменные
- •18.4.Процедурные переменные в качестве параметров
- •19.Рекурсия
- •19.1.Что такое рекурсия
- •19.2.Рекурсивные подпрограммы
- •19.3.Прямая и косвенная рекурсия
- •19.4.Предварительное (опережающее) описание подпрограммы
- •19.5.Опасности рекурсии
- •19.5.1.Бесконечная рекурсия
- •19.5.2.Глубокая рекурсия
- •19.5.3.Итерация и рекурсия, необоснованное применение рекурсии
- •19.6.Когда использовать рекурсию
- •19.7.Формы рекурсивных подпрограмм
- •19.8.Примеры рекурсивных программ
- •19.8.1.Вывод цифр целого числа в прямом порядке
- •19.8.2.Поиск максимального элемента массива
- •19.9.Задача о Ханойских башнях
- •20.Указатели
- •20.1.Указательные типы
- •Описание типизированного указателя
- •20.2.Операции с указателями
- •20.3.Примеры присваивания для указателей
- •20.4.Статические и динамические переменные
- •Создание новой динамической переменной базового типа и установка на нее указателя
- •Уничтожение динамической переменной, на которую ссылается указатель
- •Проблема потерянных ссылок
- •21.Динамические структуры данных
- •21.1.Данные статической структуры и данные динамической структуры
- •21.2.Односвязные линейные списки
- •21.2.1.Структура односвязного линейного списка
- •Вставка элемента после заданного элемента
- •21.3.Стеки
- •21.3.1.Реализация стека через односвязный линейный список
- •21.3.2.Применение стеков
- •21.3.3.Реализация стека на основе массива
- •21.4.Деревья
- •21.4.1.Основные определения
- •Алгоритм построения идеально сбалансированного дерева
- •21.4.3.Способы обхода дерева
- •Деревья поиска
- •Построение дерева поиска
21.Динамические структуры данных
21.1.Данные статической структуры и данные динамической структуры
Используемые в программировании данные можно разделить на две большие группы:
В данных статической структуры взаиморасположение и взаимосвязь элементов всегда остаются постоянными. В эту группу входят простые типы (целые, вещественные и т.д.) и структурированные типы (массивы, записи и.т.д.).
Данные динамической структуры имеют внутреннее строение, которое формируется по определенному закону, но количество элементов и их взаиморасположение могут динамически изменяться во время выполнения программы. Сюда относятся:
односвязные и многосвязные линейные списки,
кольцевые списки,
стеки, очереди, дэки, деревья, графы.
21.2.Односвязные линейные списки
21.2.1.Структура односвязного линейного списка
Односвязные линейные списки – это данные динамической структуры, состоящие из однородных элементов, линейно связанных между собой.
Для них определены следующие действия:
Добавление элемента в начало (голову) списка;
Добавление элемента в конец (хвост) списка;
Вставка элемента между двумя любыми другими элементами списка;
Удаление любого элемента списка.
Каждый элемент списка состоит из данных и ссылки на следующий элемент списка. На первый элемент списка и тем самым на весь список указывает переменная-указатель. Последний элемент содержит пустую ссылку nil.
Для представления элементов списка используют записи, например: type ref =^Elem; Elem=record inf: integer; next: ref end; Тип ref – это указатель на переменные базового типа Elem |
|
Замечание: при описании указательных типов разрешается в правой части равенства указывать идентификатор базового типа (здесь Elem), который еще не описан, но тогда его описание должно быть сделано в этом же разделе описания типов type.
Для сохранения информации о списке достаточно одной статической переменной – указателя на первый элемент этого списка (обычно его называют головой списка).
С указателем на голову списка нельзя производить никаких действий, которые могут стать причиной утери всего списка. Для работы со списком обычно заводят вспомогательный указатель, копируя в него ссылку на голову списка, например: p:=Head.
Для доступа к элементам списка будем использовать следующие конструкции:
p – адрес текущего элемента списка;
p^ – запись из двух полей, хранящаяся по адресу p;
p^.inf – первое поле этой записи;
p^.next – второе поле этой записи, являющееся адресом следующего элемента списка;
p^.next^.inf – первое поле элемента списка, следующего за тем, на который указывает р;
p^.next^.next – второе поле элемента списка, следующего за тем, на который указывает р.
21.2.2.Основные действия над односвязными линейными списками
При описании действий используются следующие переменные:
var Head,p,pred,q,pmax:ref;
x,A,tmp:integer;
Создание пустого списка
Head:=nil
Вставка элемента в начало списка
Исходный список |
Список после вставки элемента |
|
|
new(q); //Выделение в динамической памяти места для нового элемента
q^.inf:=x; //Заполнение поля данных
q^.next:=Head; //Заполнение поля ссылки
Head:=q; //Присоединение нового элемента к началу списка
Удаление первого элемента
Исходный список |
Список после удаления первого элемента |
|
|
p:=Head; //Установка текущего указателя на начало списка
Head:=p^.Next;//Установка Head на элемент, следующий за первым
Dispose(p); //Освобождение памяти, которую занимал первый элемент
p:=nil;
Проходы по списку
Проходом называют посещение всех элементов списка, начиная с головы списка.
a) Проход по списку с проверкой текущего элемента
p:=Head; {Установка текущего указателя на начало списка}
while (p<>nil) and (p^.inf<>A) do
begin
Oper(p); {Какая-либо операция над текущим элементом}
p:=p^.next {Переход к следующему элементу списка}
end;
Данный проход можно использовать:
Для поиска определенного элемента, тогда в заголовок цикла добавляется соответствующее условие, например, (p^.inf<>A), (p^.inf>0) и т.п. Если элемент найден, p указывает на него. Если не найден, p=nil.
Для выполнения какой-либо операции над элементами (вывод, суммирование, проверка на максимальность и т.д.). Тогда в тело цикла добавляются операторы или вызов подпрограммы для реализации этой операции.
b) Проход по списку с проверкой наличия элемента, следующего за текущим элементом
p:=Head;
while (p^.next<>nil) do
p:=p^.next;
После выхода из цикла p указывает на последний элемент.
Данный проход можно использовать для вставки элемента в конец списка и перед последним элементом.
c) Проход по списку с двумя указателями
pred:=nil; {pred указывает на предшествующий элемент}
p:=Head; {p – на текущий элемент}
while (p<>nil) and (p^.inf<>A) do
begin
Oper(p);{Какая-либо операция над элементами списка}
pred:=p;
p:=p^.next{Переход к следующему элементу списка}
end;
Данный проход можно использовать:
Для поиска определенного элемента, тогда в заголовок цикла добавляется соответствующее условие, например, (p^.inf<>A), (p^.inf>0) и т.п. Если элемент найден, p указывает на него, pred – на предшествующий. Если не найден, p=nil, pred указывает на последний элемент.
Для выполнения какой-либо операции над текущим и предшествующими элементами (проверка на возрастание и т.д.). Тогда в тело цикла добавляются операторы или вызов подпрограммы для реализации этой операции.
d) Проход по списку с двумя указателями и с проверкой наличия элемента, следующего за текущим
pred:=nil; {pred указывает на предшествующий элемент}
p:=Head; {p – на текущий элемент}
while (p^.next<>nil)do
begin
pred:=p;
p:=p^.next{Переход к следующему элементу списка}
end;
После выхода из цикла p указывает на последний элемент, pred – на предшествующий элемент.
Данный проход можно использовать для удаления последнего элемента.