- •Предисловие
- •Основы программирования
- •Понятие алгоритма.
- •Алгоритм Евклида.
- •Задача о поездах и мухе
- •Вместо лирического отступления
- •Этапы подготовки задачи для решения на компьютере
- •Примеры разработки алгоритмов
- •Решение квадратного уравнения.
- •Вычисление интегралов
- •Обработка результатов эксперимента
- •Решение системы линейных алгебраических уравнений
- •Введение в язык программирования 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.1 Алгоритмы сортировки
____________________________________________________________________
на
if vector[j].comp < vector[min].comp then min:= j;
4.1.3 Сортировка вставками
Алгоритм этого метода следующий: берем первые два элемента и распола-
гаем их в правильном порядке. Затем берем следующий элемент и вставляем его в нужное место среди тех, что мы уже обработали. Рассматриваемый эле-
мент вставляется в позицию посредством передвижения большего элемента на одну позицию вправо и затем размещением меньшего элемента в освободив-
шуюся позицию. На каждом шаге i элемент a[i] помещается в подходящую по-
зицию среди элементов a[1], ..., a[i-1]. Теперь элементы a[1], ..., a[i] являются упорядоченными, но не "совсем", поскольку среди оставшихся элементов a[i+1], ..., a[n] на каком-нибудь k-м шаге может найтись элемент меньший, чем a[1], ..., a[i], a[i+1], … a[k-1] и он будет вставлен в подходящее место среди этих элементов. Процесс завершится когда последний n-й элемент будет поме-
щен в подходящее для него место. Проиллюстрируем сказанное:
4 |
3 |
2 |
1 |
Рис. 4.8 Исходный массив
3 |
4 |
2 |
1 |
Рис. 4.9 Шаг первый, меняются первые два элемента
3 |
2 |
4 |
1 |
2 |
3 |
4 |
1 |
Рис. 4.10 Шаг второй, элемент "2" занял свое место, при этом "3" и "4" сдвинулись вправо.
286
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
2 |
3 |
1 |
4 |
2 |
1 |
3 |
4 |
1 |
2 |
3 |
4 |
Рис. 4.11 Шаг третий, элемент "1" занял свое место, при этом "2", "3" и "4" сдвинулись вправо.
Алгоритм будет содержать два цикла. Во внешнем цикле указатель i будет двигаться направо ( увеличиваться) начиная с 2, до n, где n количество элемен-
тов. Во внутреннем цикле указатель j сдвигается влево начиная с i-1. На каждом шаге j-м шаге происходит сдвиг элементов вправо до тех пор, пока a[i] не ока-
жется меньше a[j]. Тогда a[i] останется на этом месте и внутренний цикл за-
вершится. Внутренний цикл также может завершиться, когда будет достигнуто начало списка. Рассмотрим программу сортировки строки символов по алфави-
ту методом вставок:
program insertion_sort_string;
uses
CRT, FileUtil;
var
str: string;
{Процедура сортировки методом вставок}
procedure insert(var str: string);
var
i, j: integer;
v: char;
begin
for i:= 2 to Length(str) do
287
4.1 Алгоритмы сортировки
____________________________________________________________________
begin
v:= str[i]; j:= i - 1;
{Условие выхода из цикла: найдено подходящее место
для текущего элемента или достигнуто начало строки}
while (str[j] > v) and (j > 0) do begin
str[j+1]:= str[j]; dec(j);
end; str[j+1]:= v;
end;
end;
begin
str:= 'hgfedcba';
writeln(UTF8ToConsole('Исходная строка: '),
UTF8ToConsole(str));
insert(str);
writeln(UTF8ToConsole('Отсортированная строка: '),
UTF8ToConsole(str));
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
В этой программе мы рассматривали строку как массив символов. Для строки, состоящей из символов кириллицы, алгоритм необходимо несколько видоизменить. Внешний цикл будет начинаться с 3, так как в кодировке UTF-8
первый байт второго символа строки будет иметь номер 3.
288
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
program insertion_sort_string;
uses
CRT, FileUtil;
var
str: string;
{Процедура сортировки методом вставок кириллицы}
procedure insert_kyr(var str: string); var
i, j: integer; v, v1: string[2];
begin
for i:= 3 to Length(str) do begin
v:= Copy( str, i, 2); j:= i - 2;
{Условие выхода из цикла: найдено подходящее место
для текущего элемента или достигнуто начало строки}
while (Copy(str, j, 2) > v) and (j > 0) do begin
v1:= Copy(str, j, 2); str[j+2]:= v1[1]; str[j+3]:= v1[2]; dec(j, 2);
end;
str[j+2]:= v[1]; str[j+3]:= v[2];
end;
end;
289
4.1 Алгоритмы сортировки
____________________________________________________________________
begin
str:= 'зжедгвба';
writeln(UTF8ToConsole('Исходная строка: '),
UTF8ToConsole(str));
insert_kyr(str);
writeln(UTF8ToConsole('Отсортированная строка: '),
UTF8ToConsole(str));
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
Что будет, если строка "смешанная"? Т.е. содержит и символы кириллицы и символы латиницы. Проще всего поступить следующим образом. Просмот-
реть всю строку и сформировать две новые строки. Одна будет содержать толь-
ко кириллицу, а другая только латиницу. Затем "скормить" процедуре insert_kyr
строку с кириллицей, процедуре insert строку с латиницей. И в завершение объ-
единить отсортированные строки функцией Concat.
program insertion_sort_string;
uses
CRT, FileUtil;
var
str, str_lat, str_kyr: string;
i: integer;
{Процедура сортировки методом вставок латиницы}
procedure insert(var str: string);
var
i, j: integer;
290
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
v: char;
begin
for i:= 2 to Length(str) do
begin
v:= str[i]; j:= i - 1;
{Условие выхода из цикла: найдено подходящее место
для текущего элемента или достигнуто начало строки}
while (str[j] > v) and (j > 0) do
begin
str[j+1]:= str[j];
dec(j);
end;
str[j+1]:= v;
end;
end;
{Процедура сортировки методом вставок кириллицы}
procedure insert_kyr(var str: string); var
i, j: integer; v, v1: string[2];
begin
for i:= 3 to Length(str) do begin
v:= Copy( str, i, 2); j:= i - 2;
{Условие выхода из цикла: найдено подходящее место
для текущего элемента или достигнуто начало строки}
while (Copy(str, j, 2) > v) and (j > 0) do
291
4.1 Алгоритмы сортировки
____________________________________________________________________
begin
v1:= Copy(str, j, 2); str[j+2]:= v1[1]; str[j+3]:= v1[2]; dec(j, 2);
end;
str[j+2]:= v[1]; str[j+3]:= v[2];
end;
end;
begin
str:= 'зжедгвбаhgfedcbaиклмнijklmn'; i:= 1;
str_lat:= ''; str_kyr:= '';
while i <= Length(str) do begin
if ord(str[i]) < 128 then
begin
str_lat:= str_lat + str[i]; inc(i);
end else begin
str_kyr:= str_kyr + Copy(str, i, 2); inc(i, 2);
end;
292
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
end;
writeln(UTF8ToConsole('Исходная строка: '),
UTF8ToConsole(str));
insert(str_lat); // сортировка латиницы insert_kyr(str_kyr); // сортировка кириллицы
str:= Concat(str_lat, str_kyr);
writeln(UTF8ToConsole('Отсортированная строка: '),
UTF8ToConsole(str));
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
Напишем программу сортировки массива строк методом вставок. В про-
грамме строки сортируются по первому символу строки. Например, если задан массив из 4 строк:
Яковлев
Петров
Сидоров
Алексеев
то программа выдаст массив в следующем виде:
Алексеев
Петров
Сидоров
Яковлев
293
4.1 Алгоритмы сортировки
____________________________________________________________________
program insertion_sort_array;
uses
CRT, FileUtil;
var
str: array of string;
i, n: integer;
{Процедура сортировки методом вставок}
procedure insert(var str: array of string); var
i, j: integer; stroka: string;
begin
for i:= 1 to High(str) do begin
stroka:= str[i]; j:= i - 1;
while (str[j][1] > stroka[1]) and (j >= 0) do begin
str[j+1]:= str[j]; dec(j);
end;
str[j+1]:= stroka; end;
end;
begin
writeln(UTF8ToConsole('Введите количество строк в массиве')); readln(n);
SetLength(str, n);
294
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
writeln(UTF8ToConsole('Введите '), n); writeln(UTF8ToConsole('строк(и) символов'));
for i:= 0 to n - 1 do
readln(str[i]);
writeln(UTF8ToConsole('Исходный массив строк'));
for i:= 0 to n - 1 do
writeln(str[i]);
insert(str);
writeln(UTF8ToConsole('Отсортированный массив строк: '));
for i:= 0 to n - 1 do
writeln(str[i]);
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
Отсортируем массив менеджеров (раздел 3.6.3.3. и 4.1.2) методом вставок:
program insertion_sort_file; uses
CRT, SysUtils, OutScr, FileUtil; type
manager= record name: string[18]; comp: integer; end;
var
company: manager;
f_not_sorted, f_sorted: File of manager; vector: array of manager;
295
4.1 Алгоритмы сортировки
____________________________________________________________________
i, n: integer;
name_file: string;
{Процедура сортировки методом вставок файла по фамилиям менеджеров} procedure insert(var vector: array of manager);
var
i, j, count: integer; t: manager;
begin
count:= high(vector); for i:= 0 to count do begin
t:= vector[i]; j:= i - 1;
while (vector[j].name > t.name) and (j >= 0) do begin
vector[j + 1] := vector[j]; dec(j);
end;
vector[j + 1] := t; end;
end;
{ ================================================ } begin
{При необходимости укажите полный путь к файлу
или скопируйте файл в папку с данным проектом}
if not FileExists('File_not_sorted.dat') then
begin
writeln(UTF8ToConsole('Файлы не существуют'));
296
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
writeln(UTF8ToConsole('Сначала создайте их'));
writeln(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
exit;
end;
AssignFile(f_not_sorted,'File_not_sorted.dat');
Reset(f_not_sorted);
// Определение количества записей в файле
n:= System.FileSize(f_not_sorted);
SetLength(vector, n);
{Подготовка к внутренней сортировке,
считывание записей файла в массив,
в процедуру передается массив, а не файл.}
i:= 0;
while not Eof(f_not_sorted) do begin
Read(f_not_sorted, company); vector[i]:= company; // сортируемый массив i:= i + 1;
end;
insert(vector); // вызов процедуры сортировки методом вставок
CloseFile(f_not_sorted);
AssignFile(f_sorted, 'File_sorted.dat');
Rewrite(f_sorted);
for i:= 0 to n - 1 do Write(f_sorted, vector[i]); CloseFile(f_sorted); name_file:= 'File_sorted.dat';
{Вызов процедуры для вывода на экран сводной ведомости.
297
4.1 Алгоритмы сортировки
____________________________________________________________________
Процедура находится в модуле OutScr}
output_to_screen(name_file);
write(UTF8ToConsole('Нажмите любую клавишу'));
readkey;
end.
Во внутреннем цикле метода вставок осуществляется две проверки. Одна для нахождения подходящего места текущему элементу, а другая (j>0, если нумерация индексов начинается с 1 и j>=0, если нумерация индексов начина-
ется с 0) для предотвращения выхода за пределы левого края массива (строку символов можно рассматривать как массив, элементами которого являются от-
дельные символы строки).
Однако эта дополнительная проверка, как показывают многочисленные эксперименты, замедляют работу алгоритма почти до 7%. Выходом из этой си-
туации является помещение в первый элемент массива так называемого "сто-
рожевого" элемента, который являлся бы минимальным элементом массива. Но заранее (до начала работы алгоритма) значение минимального элемента, как правило, неизвестно. Следовательно, необходимо предварительно просмотреть весь массив, найти минимальный элемент и переместить его в начало массива
(фактически это выполнение первого цикла сортировки методом выбора). Те-
перь, когда первый элемент уже находится в требуемой позиции, можно запус-
кать алгоритм сортировки методом вставок без проверки на выход за пределы начала массива. Программа для улучшенного метода вставок выглядит сле-
дующим образом:
program modify_insertion_sort_string;
uses
CRT, FileUtil;
var
298
Глава 4 Типовые алгоритмы обработки информации
____________________________________________________________________
str: string;
{Процедура, реализующая улучшенный алгоритм
сортировки методом вставок}
procedure insert(var str:string);
var
i, j: integer;
v: char;
min: integer;
begin
{Поиск минимального элемента в строке}
min:= 1;
for i:= 2 to length(str) do
if str[i] < str[min] then min:= i;
{Меняем местами найденный символ с первым
символом в строке}
v:= str[1];
str[1]:= str[min];
str[min]:= v;
{Реализация собственно метода вставок}
for i:= 2 to length(str) do
begin
v:= str[i]; j:= i - 1;
// теперь в цикле проверяется только одно условие
while str[j] > v do
begin
str[j+1]:= str[j];
dec(j);
end;
299