- •Аннотация
- •Условия использования
- •Оглавление
- •Содержание
- •Только для взрослых
- •Десять лет спустя
- •Чему нас учат семья и школа?
- •Крошка сын к отцу пришел
- •Азбучные истины
- •Что я могу ещё сказать?
- •Благодарности
- •Детям до 16-ти
- •Глава 1 Путь далек у нас с тобою…
- •Компьютер
- •Компилятор
- •Личный багаж
- •Компьютерная литература
- •В здоровом теле – здоровый дух
- •Вместе весело шагать по просторам!
- •Повторение – мать учения
- •Соглашения
- •Итоги
- •Глава 2 Вместо теории
- •Миф о думающих машинах
- •Загадочные коды
- •Языки программирования и компиляторы
- •Следующий шаг –
- •Итоги
- •Глава 3 Консольный интерфейс
- •Что такое интерфейс?
- •Консольный интерфейс
- •Прикосновение к консольному интерфейсу
- •А почему не «окна»?
- •Итоги
- •Глава 4 Оружие – к бою!
- •Оружейный прилавок
- •Free Pascal
- •Настройка ярлыка
- •Free Pascal
- •Установка справочной системы
- •Обновление версий Free Pascal
- •Итоги
- •Глава 5 Программа номер один
- •Постановка задачи
- •Создание файла
- •Наполнение файла
- •Компиляция
- •Процедура вывода (печати)
- •Запуск программы
- •Итоги
- •Глава 6 Подготовка к следующему штурму
- •Ещё об исходных файлах
- •Управление окном редактора
- •Борьба с ошибками
- •Итоги
- •Глава 7 Развиваем успех
- •Операторы и разделители
- •Программа, стой!
- •Алгоритмы
- •Блок-схемы
- •Итоги
- •Глава 8 Постоянные и переменные
- •Константы
- •Идентификаторы
- •Переменные
- •Ввод и вывод данных
- •Итоги
- •А слабо?
- •Глава 9 Переменные: продолжение знакомства
- •Представьтесь, пожалуйста!
- •Из пустого в порожнее
- •Сцепление строк
- •Инициализация переменных
- •Типизированные константы
- •Итоги
- •А слабо?
- •Глава 10 Условный оператор
- •Стой! Кто идет?
- •Вопрос ребром
- •Пост номер один
- •Неполный условный оператор
- •Пост номер два
- •Итоги
- •А слабо?
- •Глава 11 Операторный блок
- •Операторные скобки
- •Красиво жить не запретишь
- •Комментарии
- •Итоги
- •Глава 12 Цикл с проверкой в конце
- •Подтянем дисциплину
- •Нанимаем репетитора
- •Вежливый часовой
- •Досрочный выход из цикла
- •Итоги
- •Глава 13 Правда и кривда
- •Есть ли жизнь на Марсе?
- •Информация и её мерило
- •Булевы переменные
- •Ввод и вывод булевых данных
- •Логические выражения
- •С высоты птичьего полета
- •Парад логических операций
- •Итоги
- •А слабо?
- •Глава 14 Дважды два – четыре
- •Поможем братьям нашим меньшим
- •Числа и действия с ними
- •Алгоритм экзаменатора
- •Экзаменатор, первый вариант
- •Итоги
- •А слабо?
- •Глава 15 Айда в Монте-Карло!
- •Куда ни глянь – то процедура, то функция!
- •Госпожа удача
- •Итоги
- •А слабо?
- •Глава 16 Делу время, а потехе час
- •Потемкинская лестница
- •Итоги
- •А слабо?
- •Глава 17 И вновь за парту
- •Цикл со счетчиком
- •Итоги
- •Глава 18 Аз, Буки
- •Символьный тип данных
- •Индексация
- •Длина строки
- •Распечатка строки
- •Итоги
- •Глава 19 Процедуры и функции: разделяй и властвуй
- •Снежный ком
- •Описание процедур
- •Процедуры с параметрами
- •Итоги
- •Глава 20 Процедуры: первый опыт
- •Мухи – налево, котлеты – направо!
- •Сверху вниз
- •Первые раны
- •Глобальные и локальные
- •Локально – это разумно!
- •Неподдающаяся строка
- •Итоги
- •Глава 21 Отладка
- •Отладчик
- •Жучки, вылезайте!
- •Ссылка на переменную
- •Итоги
- •Глава 22 О передаче параметров
- •Процедура обмена
- •Замена символов в строке
- •О передаче строк
- •Итоги
- •Глава 23 Функции
- •Объявление функции
- •Пример функции
- •Подсчет символов в строке
- •Возврат строк
- •Когда результат не важен
- •Неявная переменная Result
- •Итоги
- •Глава 24 Криптография
- •Секреты Юлия Цезаря
- •Суть проблемы
- •О кодировании символов
- •Чудесные превращения
- •Шифрование символа
- •Расшифровка символа
- •Итоги
- •А слабо?
- •Глава 25 Текстовые файлы
- •Файлы хорошие и разные
- •Формат текстовых файлов
- •Доступ к текстовым файлам
- •Чтение из файла
- •Последовательный доступ к файлу
- •Самореклама
- •Цикл с проверкой в начале
- •Итоги
- •Глава 26 Я не читатель, — я писатель!
- •Запись в текстовый файл
- •Пример записи в файл
- •Завершение шпионского проекта
- •Итоги
- •А слабо?
- •Глава 27 Дайте кораблю минутный отдых!
- •Ошибка ошибке рознь
- •Фатальные ошибки
- •«Простительные» ошибки
- •Опции компилятора
- •Обработка ошибок ввода-вывода
- •Директивы компилятора
- •Директиву – в студию!
- •Парад директив
- •Итоги
- •А слабо?
- •Глава 28 Редактор и справочная система
- •Небьющиеся окна
- •Буфер обмена
- •Справочная система
- •Итоги
- •Глава 29 Читайте по-новому
- •Полицейская база данных, версия 1
- •Полицейская база данных, версия 2
- •Итоги
- •Глава 30 Журнальная история
- •Статистика знает всё?
- •Строим планы
- •Барабаним по клавишам
- •Первый блин
- •Блин второй
- •Спецификатор ширины поля
- •«Развесные» числа
- •Итоги
- •Глава 31 Финал журнальной истории
- •Буква за буквой
- •Нелишняя предосторожность
- •Достройка программы
- •Испытание
- •Итоги
- •Глава 32 Порядковые типы данных
- •Типы данных: простые и сложные
- •Целое братство
- •Капля, переполняющая чашу
- •Инкремент и декремент
- •Диапазоны
- •Перечисления
- •Порядковые типы
- •Разумный контроль
- •Итоги
- •Глава 33 Вещественные числа
- •Изображение вещественных чисел
- •Вывод вещественных чисел
- •Типы вещественных чисел
- •Сравнение вещественных чисел
- •Типы данных пользователя
- •Совместимость и преобразование типов
- •Размеры переменных и типов данных
- •Итоги
- •Глава 34 Структура программы
- •Управляющие структуры
- •Структура программы
- •Структура процедур и функций
- •Обмен данными с подпрограммами
- •Встроенные процедуры и функции
- •Что дальше?
- •Итоги
- •А слабо?
- •Глава 35 Множества
- •В директорском кабинете
- •Первым делом, первым делом – оцифровка
- •Множества глазами математика
- •Числовые множества
- •Мощность множества, полные и неполные множества
- •Итоги
- •Глава 36 Множества в Паскале
- •Объявление множеств
- •Присвоение значений множествам
- •Операции с множествами
- •Сравнение множеств
- •Проверка на вхождение элемента в множество (операция IN)
- •Решение директорской задачи
- •Итоги
- •А слабо?
- •Глава 37 Ввод и вывод множеств
- •Вывод множества в текстовый файл
- •Ввод множества из текстового файла.
- •Директорская задача, первый вариант
- •Директорская задача, второй вариант
- •Итоги
- •Глава 38 Множества «в бою»
- •Активисты, шаг вперед!
- •Подвиг контрразведчика
- •В тридевятом царстве
- •Решето Эратосфена
- •Мелочь, а приятно
- •Итоги
- •А слабо?
- •Глава 39 Командная игра (массивы)
- •Снежная лавина
- •А где же волшебная палочка?
- •Массивы вокруг нас
- •Объявление массивов
- •Доступ к элементам (индексация)
- •Ввод и вывод массивов
- •Ошибки индексации
- •Итоги
- •Глава 40 Пристрелка на знакомых мишенях
- •Вопрос-ответ – добиваемся гибкости
- •Полицейская база данных – ускоряем поиск
- •Ещё раз о статистике
- •Итоги
- •Глава 41 По порядку, становись!
- •Пиратская справедливость
- •Пузырьковая сортировка
- •Электронная делёжка
- •Возвращение на футбольное поле
- •Итоги
- •Глава 42 Кто ищет, тот всегда найдет
- •Где эта улица, где этот дом?
- •Последовательный поиск
- •Двоичный поиск
- •Исследование двоичного поиска
- •Ах, время, время!
- •Логарифмы? Это просто!
- •Итоги
- •Глава 43 Сортировка по-взрослому
- •«Фермерская» сортировка
- •Быстрая сортировка
- •Процедура быстрой сортировки
- •О рекурсии и стеке
- •Алгоритмы, на старт!
- •Итоги
- •Глава 44 Строки
- •Строка – особый род массива
- •Укороченные строки
- •Операции со строками
- •Подсчет слов в строке
- •Контекстная замена
- •Итоги
- •Глава 45 Очереди и стеки
- •Вовочка в потоке событий
- •Танцевальный кружок
- •Скитания товарного вагона
- •Сортировочная горка
- •Итоги
- •Глава 46 Огромные числа
- •Сколько звезд на небе?
- •Сложение «в столбик» никто не отменял
- •Великая стройка
- •Длинная арифметика
- •Итоги
- •А слабо?
- •Глава 47 Системы счисления
- •Из тьмы веков
- •Число и его изображение
- •Десятичная система
- •Двоичная система
- •Шестнадцатеричная система
- •Другие системы счисления
- •Изображение числа в заданной системе счисления
- •Обратное преобразование
- •Итоги
- •Глава 48 Железная логика
- •Два взгляда на компьютерные «кирпичики»
- •Логические операции в регистрах
- •Сдвиги влево и вправо
- •Итоги
- •Глава 49 Сложные массивы
- •На поклон к Науке
- •Имперское строительство
- •Крестики-нолики
- •Итоги
- •А слабо?
- •Глава 50 Неспортивные рекорды (записи)
- •Кушать подано!
- •Записи
- •Второй тайм
- •Дополнительное время
- •Итоги
- •Глава 51 Указатели в море памяти
- •Погружение в оперативную память
- •«Планировка» памяти
- •Указатели, первое знакомство
- •Объявление указателей
- •Копирование указателей, пустой указатель
- •Сравнение и проверка указателей
- •Разыменование указателей
- •Нетипичный указатель
- •Примеры с указателями
- •Итоги
- •Глава 52 Динамические переменные
- •Аппетит является к обеду
- •Одолжите памяти немножко!
- •Выделение памяти
- •Освобождение памяти
- •Предупреждён – значит, вооружен
- •Итоги
- •Глава 53 Массив указателей
- •Базу данных – в кучу
- •Сортировка массива указателей
- •Итоги
- •А слабо?
- •Глава 54 Односвязные списки
- •Чудесное сочетание
- •Проблема курицы и яйца
- •Вяжем список
- •Распечатка списка
- •Поиск в несортированном списке
- •Сортированные списки
- •Поиск в сортированном списке
- •Итоги
- •Глава 55 Слова, слова, слова…
- •Частотный анализ текста
- •Слово за слово
- •Структура записи
- •Алгоритм
- •А слабо?
- •Глава 56 И снова очереди, и снова стеки…
- •Шутить изволите?
- •Танцуют все!
- •Итоги
- •Глава 57 Графомания
- •Видимое представление графа
- •Внутреннее представление графа
- •Ввод и вывод графа
- •Итоги
- •Глава 58 По графу шагом марш!
- •Империя номер два
- •Структура узла
- •В рассыпную!
- •Аты-баты
- •Итоги
- •Глава 59 Крупные проекты
- •О модулях и разделении труда
- •Модули
- •Дробление модуля – «смертельный» номер
- •Компиляция проекта
- •Инициализация модуля
- •Структура модуля
- •О совпадении имен
- •Сборочный цех
- •Фирменные библиотеки
- •Динамически загружаемые библиотеки (DLL)
- •Итоги
- •Глава 60 Мелкие хитрости
- •Включаемые файлы
- •Условная компиляция
- •Итоги
- •Глава 61 «Кубики» программиста (ООП)
- •Фокус-покус
- •Вместо паяльника
- •На трех китах
- •Инкапсуляция
- •Наследование
- •Приборостроение
- •Гражданское строительство
- •Динамические объекты
- •Полиморфизм
- •Сокрытие полей и методов
- •Итоги
- •Глава 62 Всё только начинается!
- •Крупицы мастерства
- •Программисты, на старт!
- •Приложение А Установка и настройка IDE Borland Pascal
- •Borland Pascal, состав дистрибутива
- •Borland Pascal
- •Установка
- •Организация рабочей папки
- •Создание и настройка ярлыка
- •Пробный запуск
- •Предварительная настройка
- •Русификация консольного окна
- •Turbo Pascal School Pak
- •Приложение Б Консольная программа в среде Delphi
- •Создание пустого консольного приложения
- •Настройка и сохранение консольного приложения
- •Русификация консольного приложения
- •Приложение В Особенности IDE Pascal ABCNet
- •Приложение Ж Директивы управления компиляцией
- •Приложение З Назначение пунктов меню
- •Приложение И Стандартная кодировка символов MS-DOS
- •Приложение К Некоторые встроенные процедуры и функции
- •Приложение М Пример олимпиадной задачи
- •Библиография
Глава 41 По порядку, становись!
В 39-й главе, где состоялось наше знакомство с массивами, мы намерились отсортировать футбольные команды в порядке набранных ими очков. Следуя к этой цели, перенесемся ненадолго в прошлое — лет на триста назад.
Пиратская справедливость
Тогда в морях разбойничали «джентльмены», которых мы зовем пиратами. Одной из таких бригад повелевал некто Райт. Пиратские команды не отличались дисциплиной, но Райт добился порядка на корабле, избегая жестокостей. Отважный в бою, Райт давал пример и в мирных обстоятельствах, деля добычу если не поровну, то хотя бы по справедливости. Вожак брал равную со всеми долю, потому команда чтила его и подчинялась беспрекословно.
Однажды джентльменам удачи достался сундук с золотыми слитками. Пересчитав их, пираты выяснили, что каждому из них полагается ровно по два. Казалось бы, о чем тут думать? — садись и дели. Однако слитки существенно отличались формой и размерами. Пираты не могли распилить или переплавить их, сделав одинаковыми. Как быть? — с таким вопросом Райт обратился к экипажу.
После недолгих споров разбойники уже готовы были бросить жребий (на случайную дележку никто не обижался). Но тут голос подал бывший аптекарь, а ныне корабельный лекарь по кличке Нашатырь.
— Я предлагаю, — молвил Нашатырь, — разложить слитки в порядке их веса. Затем кто-то из нас возьмет самый легкий и самый тяжелый из них. Другой — самый легкий и самый тяжелый из оставшихся, и так далее.
Свою мысль он сопроводил рисунком с шестью слитками разного веса и размера (рис. 89).
—Недурно, — согласился Райт, — но как взвесить слитки? У нас нет ни гирь, ни весов.
—Зачем мне гири? Для сравнения слитков годится вот
это, — и лекарь достал из своего сундука самодельные чашечные весы.
— Ну что ж, — сказал Райт, — ты придумал, тебе и делить.
И под пристальными взглядами всей команды лекарь принялся за дело.
Вначале ряд слитков он выложил, как попало. Затем стал по очереди сравнивать соседние куски. Если первый из них был тяжелее второго, аптекарь
294
Глава 41 По порядку, становись!
менял их местами. Так он сравнил первый и второй слитки, второй и третий, третий и четвертый и так далее до последнего слитка. В конце концов, самый тяжелый слиток оказался на последнем месте. Затем он повторил всё это ещё раз, и тогда второй по величине слиток оказался на предпоследнем месте. Проделав это N-1 раз, где N — количество слитков, лекарь выложил слитки в нужном порядке: первым лежал самый легкий, а последним — самый тяжелый.
1 |
2 |
3 |
4 |
5 |
6 |
Доля третьего пирата (3 и 4)
Доля второго пирата (2 и 5)
Доля первого пирата (1 и 6)
Рис. 89 – Пример справедливого дележа шести слитков между тремя пиратами
«А теперь бросайте жребий, — подытожил Нашатырь, скромно отходя в сторону, — пусть он определит порядок взятия долей». Пираты остались довольны.
Пузырьковая сортировка
Вернемся в наше время. О пиратской истории программист сказал бы так: разложив куски золота в нужном порядке, лекарь отсортировал массив слитков.
Его метод известен как «пузырьковая сортировка» — Bubble Sort. Откуда взялось это название? Проследите за пузырьками в стакане газировки: по мере всплытия они объединяются с другими и становятся крупнее.
Воспользуемся методом лекаря-аптекаря для сортировки массива из 10 целых чисел — это будут наши золотые слитки. А для испытания алгоритма напишем программу P_41_1, которая вначале заполнит массив случайным образом и распечатает его. Затем отсортирует этот массив и снова распечатает. Работу по сортировке выделим в отдельную процедуру по имени BubbleSort, — она ещё пригодится нам в последующих проектах.
Исследуйте процедуру сортировки по шагам. Здесь «крутятся» два цикла FOR-TO-DO, вложенные друг в друга. Внутренний цикл со счетчиком J
295
Глава 41 По порядку, становись!
сравнивает соседние числа и, при необходимости, меняет их местами. Переменная T нужна для перестановки соседних элементов. По завершении одного внутреннего цикла очередное крупное число оказывается на своем месте. Но, поскольку сортируются CSize чисел, то внутренний цикл надо повторить CSize-1 раз, — это делает внешний цикл со счетчиком I.
{P_41_1 – Сортировка массива целых чисел } const CSize = 10; { размер массива }
{объявление типа для массива }
type TGolds = array [1..CSize] of integer;
var Golds : TGolds; { массив кусков золота }
{Процедура "пузырьковой" сортировки }
{Внимание! Параметр-массив передается по ссылке! } procedure BubbleSort (var arg: TGolds);
var i, j, t: Integer; begin
for i:= 1 to CSize-1 do { внешний цикл }
for j:= 1 to CSize-1 do { внутренний цикл } { если текущий элемент больше следующего ...}
if arg[j] > arg[j+1] then begin
{ то меняем местами соседние элементы }
t:= arg[j]; |
{ временно запоминаем } |
|
arg[j]:= arg[j+1]; |
{ следующий -> в текущий } |
|
arg[j+1]:= t; |
|
{ текущий -> в следующий } |
end;
end;
Обратите внимание: сортируемый массив передан в процедуру по ссылке VAR. Передача в процедуры массивов, множеств, строк и других сложных типов данных по ссылкам CONST и VAR — обычная практика. Это повышает скорость работы программ и уменьшает объём памяти, занимаемый параматрами.
296
Глава 41 По порядку, становись!
var i:integer; { для индекса в главной программе }
begin {--- Главная программа ---}
{заполняем массив случайным образом } Randomize;
for i:=1 to CSize do Golds [i]:= 1+Random(1000);
{распечатаем до сортировки }
Writeln('До сортировки:');
for i:=1 to CSize do Writeln(Golds [i]:3);
{сортируем } BubbleSort(Golds);
{распечатаем после сортировки } Writeln('После сортировки:');
for i:=1 to CSize do Writeln(Golds [i]:3); Readln;
end.
При должном внимании вы обнаружите в этой сортировке небольшой изъян, суть которого такова. После отработки первого внутреннего цикла самый большой элемент окажется на последнем месте. А значит, на втором внутреннем цикле нет смысла сравнивать два последних элемента. На третьем проходе соответственно нет смысла сравнивать три последних элемента, — они уже лежат в нужном порядке. На этих сравнениях мы зря теряем время. Порок этот легко устранить, если поправить внутренний цикл так:
for j:= 1 to CSize – i do { внутренний цикл }
Теперь каждый следующий внутренний цикл будет на единицу короче предыдущего (ведь счетчик внешнего цикла I растет). В следующей программе мы так и сделаем.
Электронная делёжка
Рассмотрев хитрости пузырьковой сортировки, поможем теперь морским романтикам. Напишем программу для справедливой дележки золотых слитков. Основная работа уже проделана, — мы смогли отсортировать массив. Осталось лишь распечатать веса тех кусков, что достанутся каждому из пиратов. Известно, что первому пирату достанется первый и последний слитки, второму — второй и предпоследний и так далее. Иначе говоря, I-му пирату достанутся слитки с номерами I и CSize+1-I. Программа P_41_2 «делит слитки», распечатывая после сортировки веса соответствующих пар.
297
Глава 41 По порядку, становись!
{ P_41_2 – Пиратская делёжка по справедливости }
const CSize = 16; { размер массива слитков }
|
{ объявление типа для массива слитков } |
||
type |
TGolds = array [1..CSize] of integer; |
||
var |
Golds : TGolds; { массив кусков золота } |
||
|
{ Процедура "пузырьковой" сортировки } |
||
procedure BubbleSort (var arg: TGolds); |
|||
var |
i, j, t: Integer; |
|
|
begin |
|
|
|
for i:= 1 to CSize-1 do |
{ внешний цикл } |
||
|
for j:= 1 to CSize-i do |
{ внутренний цикл } |
|
|
{ если текущий элемент больше следующего ...} |
||
|
if arg[j] > arg[j+1] then begin |
||
|
{ то меняем местами соседние элементы } |
||
|
t:= arg[j]; |
{ временно запоминаем } |
|
|
arg[j]:= arg[j+1]; |
{ следующий -> в текущий } |
|
|
arg[j+1]:= t; |
|
{ текущий -> в следующий } |
end; |
end; |
|
|
|
|
|
var i:integer; { используется в качестве индекса в главной программе } begin
{заполняем массив случайным образом } Randomize;
for i:=1 to CSize do Golds[i]:= 500 + Random(500);
{сортируем }
BubbleSort(Golds);
Writeln('По справедливости:');
for i:=1 to (CSize div 2) do begin { два куска по отдельности }
Write(i:2, Golds[i]:5,' + ',Golds[CSize+1-i]:3,' = '); { сумма двух кусков } Writeln(Golds[i]+Golds[CSize+1-i] :4);
end;
Readln;
end.
Вот результат одной из таких делёжек:
298