- •Предисловие
- •Основы программирования
- •Понятие алгоритма.
- •Алгоритм Евклида.
- •Задача о поездах и мухе
- •Вместо лирического отступления
- •Этапы подготовки задачи для решения на компьютере
- •Примеры разработки алгоритмов
- •Решение квадратного уравнения.
- •Вычисление интегралов
- •Обработка результатов эксперимента
- •Решение системы линейных алгебраических уравнений
- •Введение в язык программирования Pascal
- •Основные элементы языка
- •Переменные. Стандартные типы.
- •Операции отношения
- •Раздел описаний переменных
- •Выражения. Порядок выполнения операций.
- •Константы
- •Комментарии в программе
- •Операторы
- •2.1.7.1. Оператор присваивания
- •2.1.7.2. Операторы ввода/вывода
- •2.1.7.3. Операторы инкремента и декремента
- •Среда разработки Lazarus
- •Русский язык в консольных приложениях
- •Первая программа
- •Открытие существующего проекта
- •Другие способы создания консольных приложений
- •Типовой пустой проект
- •Операции с целыми числами
- •Вместо лирического отступления 2
- •Стандартные функции с целыми аргументами
- •Операции с вещественными числами (тип real).
- •Форматирование вывода
- •Одновременное использование вещественных и целых чисел.
- •Другие стандартные функции с вещественными аргументами
- •Булевы переменные
- •Условные операторы.
- •2.1.22.1 Оператор if …. then
- •2.1.22.2. Оператор if …then ... else
- •Операторы цикла
- •2.1.23.1. Оператор цикла с предусловием
- •2.1.23.2. Оператор цикла с постусловием
- •2.1.23.3. Оператор цикла с параметром.
- •2.1.23.4. Второй вариант оператора цикла с параметром
- •Оператор выбора case
- •Организация простейшего контроля ввода данных.
- •Вычисление сумм сходящихся рядов
- •Реализация некоторых алгоритмов главы 1.
- •Программа решения задачи о поездах и мухе
- •Программа вычисления определенного интеграла
- •Более сложные элементы языка
- •Общая структура Паскаль – программы
- •Процедуры и функции
- •3.1.1.1 Структура процедуры
- •3.1.1.2. Структура функции
- •3.1.1.3 Глобальные и локальные переменные
- •3.1.1.4 Способы передачи параметров
- •3.1.1.5 Процедуры завершения
- •Еще раз о типах данных
- •Классификация типов данных
- •3.2.1.1 Целый тип
- •3.2.1.2. Интервальный тип
- •3.2.1.3. Перечислимый тип
- •3.2.1.4. Множества
- •3.2.1.5. Логический тип
- •3.2.1.6. Вещественный тип
- •3.2.1.7. Указатели
- •Обработка символьной информации в Паскале
- •Символьные и строковые типы данных.
- •3.3.1.1. Тип Char
- •3.3.1.2. Функции для работы с символами
- •3.3.1.3. Тип String
- •3.3.1.4. Строковые процедуры и функции
- •Массивы
- •Динамические массивы
- •Программа решения системы линейных алгебраических уравнений методом Гаусса
- •3.4.1.1. Вариант 1 – с goto
- •3.4.1.2. Вариант 2 – без goto
- •3.4.1.3. Вариант 3 – наилучшая реализация
- •Модули в Паскале
- •Структура модуля
- •Системные модули
- •3.5.2.1. Модуль CRT
- •Файлы
- •Тип данных – запись
- •Файловые типы
- •Процедуры для работы с файлами
- •3.6.3.1. Общие процедуры для работы с файлами всех типов
- •3.6.3.2. Процедуры для работы с текстовыми файлами
- •3.6.3.3. Процедуры для работы с типизированными файлами
- •3.6.3.4. Процедуры для работы с нетипизированными файлами
- •3.6.3.5. Организация контроля ввода/вывода при работе файлами
- •3.6.3.6. Создание простой базы данных с типизированными файлами.
- •Алгоритмы сортировки
- •Обменная сортировка (метод "пузырька")
- •Сортировка выбором
- •Сортировка вставками
- •Метод быстрой сортировки
- •Алгоритмы поиска
- •Поиск в массивах
- •Вставка и удаление элементов в упорядоченном массиве
- •Динамические структуры данных
- •Представление в памяти компьютера динамических структур.
- •Реализация стека с помощью массивов
- •Указатели
- •Стандартные операции с линейными списками
- •Реализация динамических структур линейными списками
- •4.3.6.1. Реализация стека
- •4.3.6.2. Реализация очереди с помощью линейного списка
- •4.3.6.3. Реализация двоичного дерева с помощью линейного списка
- •Сортировка и поиск с помощью двоичного дерева
- •Три источника и три составные части ООП.
- •Классы и объекты.
- •Обращение к членам класса.
- •Инкапсуляция
- •Спецификаторы доступа.
- •Свойства.
- •Наследование
- •Полиморфизм
- •Раннее связывание.
- •Позднее связывание.
- •Конструкторы и деструкторы.
- •Элементы графического интерфейса
- •Различия между консольными и графическими приложениями
- •Визуальное программирование в среде Lazarus
- •Создание графического приложения
- •Форма и ее основные свойства
- •Компоненты
- •Обработчики событий
- •Простейшие компоненты
- •6.3.5.1. Компонент TLabel
- •6.3.5.2. Кнопки TButton, TBitBtn и TSpeedButton
- •6.3.6.1. Компонент TEdit
- •6.3.6.2. Компонент TLabeledEdit
- •6.3.7.1. Компонент TMaskEdit
- •Специальные компоненты для ввода чисел
- •Тестирование и отладка программы
- •Компоненты отображения и выбора данных
- •6.3.10.1. Компонент TMemo
- •6.3.10.2. Компонент TStringGrid
- •6.3.10.3. Компоненты выбора
- •Компонент TListBox
- •Компонент TComboBox
- •Компоненты выбора – переключатели
- •6.3.10.4. Компоненты отображения структурированных данных
- •Компонент TTreeView
- •Компонент TListView
- •Организация меню. Механизм действий - Actions
- •6.3.11.1. Компонент TMainMenu
- •6.3.11.2. Компонент TToolBar
- •6.3.11.3. Компонент TActionList
- •6.3.11.4. Создание приложений с изменяемыми размерами окон
- •Послесловие
- •Литература
- •Алфавитный указатель
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
Если в конце списка вместо пустого указателя nil поставить ссылку на начало списка, т.е. на первый элемент списка, то получим так называемый
кольцевой список.
Для всех видов списков можно определить стандартные операции, которые производятся над списками и которые должен уметь реализовывать програм-
мист. К таким операциям относятся добавление нового элемента в список, уда-
ление элемента из списка, поиск нужного элемента в списке. Рассмотрим их.
4.3.5 Стандартные операции с линейными списками
Запишем стандартные операции с линейными списками в виде готовых
процедур и функций.
Процедура добавления (вставки) нового элемента в список:
procedure Insert_MyList(Elem: integer;
var pHead, pCurrent: PMyList);
{pHead - указатель на первый элемент списка ("голову" списка)
pCurrent - указатель на текущий элемент списка}
var
p: PMyList; // рабочий указатель
begin |
|
new(p); |
// заводим новый элемент |
p^.data:= |
Elem; // записываем в него данные |
{Если список был пустой, то головой списка становится p} if pHead = nil then
begin
p^.next:= nil; pHead:= p;
end
365
4.3 Динамические структуры данных
____________________________________________________________________
else
begin
p^.next:= pCurrent^.next; { в новом элементе делаем ссылку на следующий элемент, который был до вставки} pCurrent^.next:= p; {в текущем элементе делаем
ссылку на новый}
end;
pCurrent:= p; // текущим становится новый элемент
end;
Функция поиска элемента в списке просто проходит все элементы списка по ссылкам от начала до тех пор, пока не будет найден искомый элемент.
function Search_MyList(Elem: integer;
var pHead: PMyList): boolean;
var
p: PMyList; begin
if pHead <> nil then p:= pHead
else begin
writeln(UTF8ToConsole('Список пуст'));
exit;
end;
Search_MyList:= false;
while true do
begin
if p^.data = Elem then
366
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
begin
Search_MyList:= true; break;
end else
if p^.next = nil then break; p:= p^.next;
end;
end;
Функция возвращает true, если требуемый элемент найден.
Процедура удаления элемента из списка:
procedure Delete_MyList(Elem: integer;
var pHead, pCurrent: PMyList);
var
p: PMyList;
pPrev: PMyList; // предыдущий элемент списка find: boolean;
begin
if pHead <> nil then p:= pHead
else begin
writeln(UTF8ToConsole('Список пуст'));
exit;
end;
find:= false;
while true do
begin
367
4.3 Динамические структуры данных
____________________________________________________________________
if p^.data = Elem then
begin
find:= true; break;
end else
if p^.next = nil then break; pPrev:= p;
p:= p^.next; end;
if find then begin
if p = pHead then // если удаляется первый элемент begin
p:= pHead^.next; // запоминаем ссылку на следующий элемент
Dispose(pHead); |
// удаляем первый элемент списка |
pHead:= p; |
// головой списка становится p |
end |
|
else |
|
begin // если удаляется не первый элемент
pPrev^.next:= p^.next; { в предыдущем элементе заменяем ссылку на следующий элемент после удаляемого }
Dispose(p);
pCurrent:= pPrev; // текущим делаем предыдущий элемент
end;
writeln(UTF8ToConsole('Элемент успешно удален'));
end
else writeln(UTF8ToConsole('Элемент не найден'));
end;
368
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
Процедура, прежде чем удалить элемент, должна его найти. Эта часть сов-
падает с функцией поиска. Поскольку код функции поиска небольшой, мы вставили в процедуру непосредственно сам код. В принципе, в процедуре мож-
но вызвать функцию поиска. Для этого необходимо видоизменить функцию та-
ким образом, чтобы она возвращала ссылку на найденный элемент. Если эле-
мента нет, она должна возвращать nil. Предоставляем изменить функцию поис-
ка самому читателю.
Напишем главную программу работы со списком (не забудьте включить в программу процедуры и функции, которые мы только что разобрали):
program operation_list; {$mode objfpc}{$H+} uses
CRT, FileUtil; type
PMyList = ^TMyList; TMyList = record data: integer; next: PMyList; end;
var
pHead, pCurrent: PMyList; Elem, choose: integer;
{Сюда добавьте процедуры и функции, реализующие стандартные операции с линейными списками }
begin
pHead:= nil;
pCurrent:= nil;
repeat
369
4.3 Динамические структуры данных
____________________________________________________________________
writeln(UTF8ToConsole('Выберите нужное действие:')); writeln(UTF8ToConsole('1-ввод элемента списка')); writeln(UTF8ToConsole('2-поиск элемента списка')); writeln(UTF8ToConsole('3-удаление элемента списка')); writeln(UTF8ToConsole('4-просмотр всего списка')); writeln(UTF8ToConsole('5-выход из программы')); readln(choose);
case choose of
1: begin {ввод элемента списка} writeln(UTF8ToConsole('Введите элемент списка')); readln(Elem);
Insert_MyList(Elem, pHead, pCurrent); end;
2: begin {поиск элемента списка}
writeln(UTF8ToConsole('введите искомый элемент'));
readln(Elem);
if Search_MyList(Elem, pHead)then
writeln(UTF8ToConsole('Элемент найден'))
else
writeln(UTF8ToConsole('Элемент не найден')); end;
3: begin {удаление элемента списка} writeln(UTF8ToConsole('введите элемент')); readln(Elem);
Delete_MyList(Elem, pHead, pCurrent); end;
4: begin {Вывод списка на экран}
writeln(UTF8ToConsole('Элементы списка:'));
370
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
writeln;
view_MyList (pHead);
writeln;
end;
end; { end of case }
until choose = 5;
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
Кроме того, часто встречаются особые списки, где добавление или удале-
ние элементов производится только в начале или в конце списка. Какие это списки:
линейный список, в котором добавление или удаление элементов про-
изводится только в одном конце. Читатель, наверное, уже догадался, что это есть не что иное, как стек!
линейный список, в котором добавление элементов производится на од-
ном конце, а удаление на противоположном конце списка. Если внима-
тельно подумать, то работа такого списка будет напоминать живую оче-
редь людей в магазине. Поэтому такой список так и называют – очередь.
Часто очередь называют структурой FIFO (First In - First Out, т.е. "первый пришел, первый ушел").
линейный список, в котором все добавления и удаления производятся с обоих концов списка. Такой список носит название дек.
Реализуем рассмотренные динамические структуры с помощью линейных списков.
371