![](/user_photo/2706_HbeT2.jpg)
Иванова Г.С. - Основы программирования
.pdf5. Модульное программирование
( |
Начало j |
Г |
Начало |
j |
|
Ввод |
/ |
Ввод |
Т |
|
m |
|
|
|
|
i=l,m,l |
|
a=(I,l,l, |
|
|
1,1,1,1,1,1,1) |
|
||
|
|
|
||
|
a[l] = i |
|
|
|
К |
J=b"^»i |
|
Вывод |
/ |
|
|
|
a(n) |
/ |
/
a[21=j
k=l,m,l
a[3] = k
n=I,m,I
a[4] = n
Вывод /
a(4) /
/
{Конец J
Рис. 5.18. Два варианта алгоритма генерации комбинаций:
а-с использованием вложенных циклов;б-программно-реализуемый счет^шк
Program ex; Const
a:array[L, 10] ofbyte^d 7,7,7,7,7,7,7,7,7;; Fbr Im^n:integer;
181
Часть I. Основы алгоритмизации и процедурное программирование
Begin ReadLn(ri,m);
while aflj<m+l do {условие «сброса» счетчика} begin
for i:=] to n do Write(a[i]); (вывод комбинации} WriteC У;
a[n]:=afnj+l; {добавление 1 в последний разряд}
for i:=n downto 2 йЬ{анализ и осуществление переносов} ifa[i]>m then
begin afij:=l;
a[i'l]:^a[i'l]+l:
end;
end End
Ассоциируя комбинации счетчика с вариантами данных и проверяя по лученные комбинации по критериям конкретной задачи, можно осуществить полный перебор вариантов.
Как уже упоминалось выше, для реализации ограниченного перебора используется вторая стратегия, при которой генерацию и анализ комбинаций исходных данных выполняют поэтапно. С этой целью удобно использовать рекурсию, при которой процесс генерации комбинации продолжается, пока полученная часть комбинации перспективна, или не исчерпаны все вариан ты.
Пример 5.18. Задача о расстановке ферзей. Разработать программу, ко торая формирует все возможные варианты расстановки m (m>3) ферзей на шахматной доске mxm клеток, при которых ферзи не «бьют» друг друга.
Начнем с выбора способа представления данных задачи. С первого взгляда кажется, что доска должна представляться матрицей, а местоположе ние ферзей - размещением символов «*» в матрице. Однако заметим, что го раздо удобнее вариант, при котором доска представлена вектором. Индекс вектора в таком представлении соответствует номеру столбца доски, а значе
1 2 3 4 |
|
|
|
ние - номеру строки, в которой располо |
||
|
|
|
жен ферзь (рис. 5.19). |
|
||
* |
|
|
|
Определим, |
что для |
векторного |
* |
(=:0> 1 3 |
I 1 4 | |
2 | |
представления означает «бьет». Ферзь j |
||
* |
«бьет» ферзь i, если они расположены на |
|||||
* |
1 2 |
3 |
4 |
одной диагонали, |
вертикали |
или гори |
зонтали. При векторном представлении шахматной доски расположение на од ной вертикали невозможно, следователь но, необходимо проверять два условия:
182
5. Модульное программирование
pole[j] = poIe[i] - одна горизонталь;
I Pol^LJ] " pole[i] I =1 j - i I - одна диагональ.
Для определения всех вариантов расстановок ферзей, удовлетворяющих условию задачи, необходимо проверить все возможные варианты расстано вок.
Полный перебор. Полный перебор будем реализовывать в соответствии с алгоритмом, описанным в начале данного раздела. Ниже приведена про грамма, реализующая стратегию полного перебора для данной задачи. Она включает две функции: функцию генерации вариантов расстановки и функ цию проверки комбинации.
Функция генерации вариантов возвращает в точку вызова булевское зна чение: true - если еще есть варианты, false - если просмотрены все вариан ты. Следующий вариант расстановки возвращается через параметр-перемен ную pole.
Функция проверки комбинаций для каждых двух ферзей на доске прове ряет условие «бьет». Если хотя бы один раз это условие выполняется, то дан ный вариант не является решением.
Program ex;
Type p=arrayfl.. 100] of integer; Var pole.'p;
i,m:integer;
{функция проверки комбинации}
Function newj-(m:integer;pole:p).boolean; Var iJ: integer;
Begin new_r:=false;
for i:=I to m-J do forj:=i+l to m do
if(pole[i]='polelj]) or(abs(polelj]'pole[i])==j'i) then exit; new_r:-true;
End;
{функция генерации вариантов}
Function Variantfm:integer; Var pole:p):boolean; Var i:integer;
Begin polefmJ:=pole[mJ+I;
for i:=m downto 2 do ifpole[i] > m then
begin pole[i]:=l;
polefi'l]: =^polefi'IJ+1;
end;
183
Часть I. Основы алгоритмизации и процедурное программирование
ifpoIefJJ <=т then {если есть еще варианты}
Variant: =true else Variant:'='false;
End;
{основная программа}
Begin
WritelnCВведите размер |
доски'); |
ReadLn(m); |
|
for i:=l to m dopole[i]:=l; |
{исходная комбинация} |
repeat |
|
if Newr(m,pole) then |
{проверяем расстановку} |
begin
for i:=l to m do Write(pole[i]:2); Writein;
end;
until not Variant(m,pole); {если есть варианты, то генериру ем новый вариант}
End
Недостаток полного перебора, как уже говорилось выше, заключается в том, что вычислительная сложность данного решения составляет 0(т"^).
Ограниченный перебор, реализованный с использованием рекурсии. Для генерации комбинаций будем использовать древовидную рекурсию, на каж дом уровне которой ставится один ферзь m различными способами. При этом появляется возможность проверки перспективности уже имеющейся комбинации. Поясним сказанное на примере доски 4x4.
На первом шаге первого ферзя можно поставить на одно из четырех по лей первого вертикального ряда, что соответствует комбинациям
]..., 2...,3...,4....
На втором шаге второго ферзя можно поставить на одно из четырех по лей второго вертикального ряда. При этом мы получим 4 комбинации для каждого варианта установки первого ферзя:
11.., 12.., 13.., 14.. 21.., 22.., 23.., 24..
31.., 32.., 33.., 34..
41.., 42.., 43.., 44..
На этом этапе уже можно исключить все варианты, для которых первые два ферзя «бьют» друг друга: 11.., 12.., 21.., 22.., 23.., 32.., 33.., 34.., 43.., 44.. Генерацию остальных комбинаций необходимо продолжить, установив тре тьего ферзя одним из четырех способов и исключив неперспективные реше ния. На последнем этапе необходимо установить четвертого ферзя и опять
184
5, Модульное программирование
1421 |
1422 |
1423 |
1424 |
2411 2412 2413 |
2414 |
Рис.5.20. Дерево вариантов с отсечением неперспективных ветвей
исключить варианты, в которых ферзи бьют друг друга. Оставшиеся вариан ты являются решениями задачи.
На рис. 5.20 показан фрагмент дерева генерации вариантов для m = 4 с отсечением неперспективных ветвей. Первое найденное решение - комбина ция 2413.
На рис. 5.21 показаны алгоритм основной программы, ре1о^рсивной под программы добавления ферзя ferz и функции проверки перспективности по лученной комбинации new_r, а ниже приведена соответствующая програм ма.
Program ex;
Type p=arrayfl.. lOOJ ofinteger; Varpole:p;
km:integer;
{функция проверки перспективности комбинации}
Function new_r(n:integer;poIe:p):boolean; Varj:integer;
Begin newjr:-false; for j:-l to n-1 do
if (polelj]'='pole[n])or(abs(pole[j]-pole[n])=n-j) then exit; newJ*:-true;
End;
{рекурсивная функция генерации комбинации}
Procedureferz(n,m:integer; varpole:p); Var i:integer;
185
Часть 1. Основы алгоритмизации и процедурное программирование
|
|
|
newr "\ |
V(n,m,pole)y |
|
|
|
C(n,pole) J |
|
( |
Начало |
j |
new r=true |
|
|
|
|||
/ |
Ввод |
У |
|
|
L—JZ—J |
|
|
ferz (l,m,poIe)
Г Конец j
Рис. 5.21. Алгоритмы основной программы {а), функции проверки перспективности полученной комбинации (б)
и рекурсивной процедуры добавления ферзя {в)
Begin
ifn=m+I then {если установлено m ферзей, то вывести решение} begin
for i:=J to m do Write(pole[ij: 2); WriteLn;
end
else {иначе - пытаемся установить следующего ферзя} for i:=I to m do {m способами}
begin
pole[nJ:=i; {установка п-го ферзя}
if new_r(n,pole) {проверка перспективности комбинации} thenferz(n'^l,m,pole); {рекурсивный вызов установки
следующего ферзя}
end;
End;
{основная программа}
Begin
WriteLn('Beedume размер доски: *); ReadLn(m);
186
|
5. Модульное программирование |
|
|
|
|
|
Т а б л и ц а 5.1 |
|
Количество вариантов, |
Количество вариантов, |
Количество |
Размер доски |
которое проверяется |
рассмотренных при |
полученных |
|
при полном переборе |
ограниченном переборе |
решений |
4x4 |
44 = 256 |
17 |
2 |
5x5 |
55 = 3125 |
54 |
10 |
6x6 |
66 = 46656 |
153 |
4 |
7x7 |
V = 823543 |
552 |
40 |
8x8 |
88=16777216 |
2057 |
92 |
к:=0;
ferz(hmypole);
End,
Процедуру new_r используют для проверки уже сгенерированной ком бинации (уровень п соответствует попытке установить п-го ферзя). Процеду ра ferz рекурсивна. На каждом уровне она может породить до m рекурсивных вызовов (в соответствии с деревом генерации вариантов). Однако общее ко личество рассматриваемых вариантов резко уменьшается, так как неперспек тивные комбинации отсекаются, что наглядно представлено в табл. 5.1.
Задания для самопроверки
Задание I. Разработайте рекурсивную подпрофамму, осуществляющую поиск комбинации для отпирания кодового замка по методу перебора с отсечением непер спективных комбинаций. Замок представляет собой набор из п переключателей, каж дый из которых может находиться в положении «включено» или «выключено». За мок открывается при одном положении переключателей, причем в положении «включено» может находиться не более половины переключателей.
Задание 2. Разработайте рекурсивную подпрограмму, которая формирует из за данного списка предметов определенной стоимости и веса набор, вес которого не превышает заданного, а стоимость максимальна.
187
6. ФАЙЛОВАЯ СИСТЕМА, ФАЙЛЫ
Файлам называют именованную последовательность элементов данных (компо нент файла), расположенных, как правило, во внешней памяти: на дискетах, винчестере, CD или других устройствах хранения информации, также устройствах ввода-вывода. В файле может храниться текст, программа, числовые данные, фафическое изображение и т.д. Для организации работы с файлами профамма на Borland Pascal взаимодействует с операционной системой MS DOS.
6.1. Файловая система MS DOS
Как сказано выше, каждый файл обязательно имеет имя. Имена файлов
вMS DOS подчиняются определенным правилам:
•имя файла должно содержать не менее одного и не более восьми сим
волов;
•имя файла может иметь расширение, которое отделяется от имени точ кой и содержит не более трех символов;
•для записи имен и расширений могут использоваться строчные и про
писные буквы латинского алфавита a-z, A-Z, арабские цифры и некоторые специальные символы, например, символ подчеркивания «_» или знак дол лара «$»;
• в качестве имен запрещается использовать некоторые буквенные соче тания, которые зарезервированы операционной системой для обозначения устройств, например: PRN, CON, NUL, COMI, COM2, AUX, LPT1, LPT2, LPT3.
В операционных системах типа Windows некоторые из этих правил от меняются, например, имя файла может содержать больше восьми символов и включать символы русского алфавита. Однако при работе с файлами из Borland Pascal лучше придерживаться правил MS DOS.
Независимо от используемой операционной системы имена обычно со ставляют так, чтобы они указывали на содержимое файла. Расширение обыч но определяет тип хранящихся данных.
188
6. Файловая система. Файлы
Существуют стандартные расширения, используемые операционной си стемой, например:
СОМ, ЕХЕ ~ исполняемые файлы (загрузочные файлы программ); PAS, BAS, СРР - файлы исходных текстов программ на алгоритмичес
ких языках ПАСКАЛЬ, БЭЙСИК и C++ соответственно.
Для удобства работы с группами файлов применяют групповые имена файлов с использованием символов «*» и «?», где «*» соответствует любой последовательности символов, а «?» - одному любому символу, например:
*• ЕХЕ - все файлы с расширением ЕХЕ; А*. СОМ - все файлы типа СОМ с именами на букву «А»;
??В. PAS - все файлы типа PAS, имена которых содержат три символа, последний из которых «В»;
PRG1.* - файлы любых типов с именем PRG1; *.* - все файлы.
Для того чтобы MS DOS могла размещать файлы на дисках, последние должны быть специальным образом размечены (форматированы). Разметка осуществляется средствами используемой операционной системы. Если форматируется диск, бывший в употреблении, то вся хранившаяся на нем ин формация уничтожается и восстановлению не подлежит.
Как правило, диски хранят большое количество файлов (количество их на жестких дисках обычно исчисляется тысячами). Для удобства и ускорения работы с таким количеством файлов применяется древовидная структура ка талогов, аналогичная библиотечной.
Главным является корневой каталог, не имеющий имени и создаваемый в процессе форматизации диска системой. Файл корневого каталога состоит из записей, содержащих информацию о файлах, хранящихся на диске. В ка честве файлов главного каталога могут фигурировать пользовательские ка талоги, т.е. каталоги второго уровня (подкаталоги), каждый из которых мо жет содержать подкаталоги следующего уровня. Таким образом, получается дерево каталогов (рис. 6.1). Подкаталоги создаются и уничтожаются пользо вателем с помощью специальных команд. Все каталоги, кроме корневого, имеют имена, образованные по общим правилам операционной системы.
Чтобы найти файл, системе требуется просмотреть всю цепочку катало гов на пути от корневого каталога до подкаталога, хранящего сведения о тре буемом файле. Таким образом, чтобы сослаться на файл, нужно указать не только его имя, но и перечислить все предшествующие каталоги. Перечень имен каталогов на пути к файлу называется маршрутом или путем.
Перечисляемые в маршруте каталоги разделяются символом «\», причем перечень начинается с символа «\», так как корневой каталог не имеет име ни. Например:
189
Часть L Основы алгоритмизации и процедурное программирование
Рис. 6.1. Пример дерева каталогов
\katl\kat3\
Полное имя файла содержит также имя диска, на котором расположен файл. Например:
c:\katl\ kat3\file5.dat
Такая организация позволяет в разных подкаталогах создавать файлы с одинаковыми именами. Подкаталоги тоже могут иметь одинаковые имена, если они подчинены разным подкаталогам более высокого уровня.
6.2.Файлы Borland Pascal
ВBorland Pascal файл определяется как последовательность компонен тов, относящихся к одному типу: файл записей, файл целых чисел, файл строк и т. п. Особенностью файлов по сравнению с другими структурными типами данных является то, что в любой момент доступен только один ком понент. Количество компонентов файла заранее не определяется. Макси мальный размер файла, размещенного во внешней памяти, ограничивается лишь техническими возможностями вычислительной системы.
Различают дисковые файлы и логические устройства.
Дисковый файл представляет собой поименованную область внешней памяти на устройстве хранения информации, например, дискете или винчес тере. Физически операции ввода-вывода с файлами выполняются с исполь зованием специального буфера. Так, выводимые записи вначале помещают-
190