Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на ПАСКАЛЕ.doc
Скачиваний:
12
Добавлен:
04.09.2019
Размер:
2.98 Mб
Скачать

8.2.3. Действия над множествами

В Паскале, как и в математике, над множествами можно выполнять следующие логические операции:

– объединение;

– пересечение;

– разность.

Рассмотрим эти операции подробно, но предварительно произведем описание:

type COUNTRIES = (ENG, FR, USA, SP, IT);

var MAP1, MAP2: COUNTRIES.

а) ОБЪЕДИНЕНИЕ (+) : [ENG, FR] + [IT] = [ENG, FR, IT];

б) ПЕРЕСЕЧЕНИЕ (*) : [ENG, FR, USA] * [ENG, USA, IT] = [ENG, USA];

в) РАЗНОСТЬ (-) : [ENG..IT] – [ENG..SP] = [IT].

Эти три операции используются для построения выражений над множествами, например:

MAP1 := [FR];

MAP1 := MAP1 + [USA];

MAP2 := MAP1;

MAP1 := MAP1 * (MAP2 + [IT]).

П р и м е р. Решето Эратосфена. Найти все простые числа, не превосходящие заданного числа.

Алгоритм базируется на вычеркивании чисел, кратных выбранному.

program ERATOS;

const MAXPRIM = 15;

var PRIMES: set of 2..MAXPRIM;

COUNT, MULTIPLE: integer;

begin

¦ writeln ('простые числа, меньше ', MAXPRIM);

¦ PRIMES := [2..MAXPRIM];

¦ for COUNT := 2 to MAXPRIM do

¦ if COUNT in PRIMES then

¦ begin

¦ ¦ writeln (COUNT);

¦ ¦ for MULTIPLE := 1 to (MAXPRIM div COUNT) do

¦ ¦ PRIMES := PRIMES - [COUNT*MULTIPLE]

¦ end;

end.

Примечание. Программа работает с множеством, состоящим из всех целых чисел в интервале 2 ... 15. В ней при помощи цикла FOR проверяется каждое целое число, входящее в множество. Если оно является элементом множества, то печатается и из множества удаляются все целые числа, кратные данному числу.

8.3. Вывод множеств

При работе с множествами немаловажным является вопрос вывода на экран элементов множества. Отметим, что в большинстве версий языка в операторах WRITE нельзя называть переменные типа ARRAY. Например, нельзя вывести множество таким образом:

VAR A : SET OF 1..9;

...................

WRITE (A).

Здесь нет ничего удивительного, так как даже если А есть массив, то его тоже нельзя распечатать сразу с помощью одного оператора WRITE (А). Для вывода элементов массива организуются циклы.

Для вывода элементов множества также нужно организовать цикл (однократный), внутрь которого вводится некоторая переменная, пробегающая все возможные значения этого множества, а перед оператором WRITE в рамках конструкции IF проверяется, входит ли этот элемент в конкретное множество:

if K in SET1 then write (K).

Как правило, для целей распечатки элементов множеств организуются свои процедуры. Пусть мы имеем дело с множествами, состоящими из целых чисел в границах NIZ и VERH. Зададим множественный тип TS для этих границ:

type INT = NIZ..VERH; TS = set оf INT.

Тогда можно написать процедуру, содержащую в качестве параметра множество:

procedure PRINTSET (OS : TS);

var M: INT;

begin

¦ for M := NIZ to VERH do

¦ if M in OS then writeln (M);

end.

Теперь можно обращаться к этой процедуре для печати множеств, если только они состоят из элементов, не выходящих из интервала NIZ …VERH. Пусть в разделе констант было описано:

const NIZ = 0; VERH = 10.

Тогда можно вывести на экран элементы множества, обратившись к процедуре:

а) PRINTSET ([5, 6, 7]);

б) PRINTSET ([2]);

в) PRINTSET ([3..8]).

Обращение к процедуре можно организовать также в виде:

var SET1, SET2 : TS;

..................

SET1:= [...]; SET2 := [...]

PRINTSET (SET1); PRINTSET (SET1 + SET2); и т.д.

П р и м е р . В заключение рассмотрим пример целиком, где продемонстрируем все те действия, которые определены над множествами.

program IGRA;

type KOST = 1..6; BROSOK = set of KOST;

var A, B, C : BROSOK;

procedure SRAWNENIE (D : BROSOK);

var K : KOST;

begin

¦ for K := 1 to 6 do

¦ if K in D then write (K:4); writeln;

end;

begin

¦ A := [1, 3, 4]; B := [2, 4, 6];

C := A + B;

¦ write ('[1, 3, 4] + [2, 4, 6] ='); SRAWNENIE (C);

¦ C := A – B;

¦ write ('[1, 3, 4] – [2, 4, 6] ='); SRAWNENIE (C);

¦ C := A * B;

¦ write ('[1, 3, 4] * [2, 4, 6] ='); SRAWNENIE (C);

end.

Примечание. В программе определяются множества A, B, C типа BROSOK, элементами которых являются целые числа из диапазона [1..6], и процедура вывода на экран элементов таких множеств.

Затем задаются множества A и B, находятся различные значения множества C и выводятся его элементы.

Замечание 1. Если множество задано перечислимым типом, то его элементы напечатать нельзя. На печать можно вывести элементы только ординального типа: INTEGER, CHAR, BOOLEAN, интервальный.

Замечание 2. Один и тот же набор данных можно организовать в виде линейного массива ARRAY, в виде множества SET и в виде строки типа STRING. Какой из этих видов предпочтительнее? Если над элементами (числами) производятся действия, то лучше ARRAY. Если же стоит задача о взаимосвязи элементов нескольких множеств или вопрос о вхождении каких-то объектов в множество, то лучше SET.

Например, проверить, входит ли некоторая буква в заданный текст, можно двумя способами:

var TX : set of 'a'..'z';

BW : char;

----------------

TX := [‘a’..’m’];

Readln (BW);

1-й с п о с о б 2-й с п о с о б

OTWET := 'нет';

for k := 1 to 20 do if BW in TX then writeln ('да').

if BW = TX [k] then OTWET := ‘да’;

writeln (ОTWET);

Из приведенных фрагментов программ видно, что 2-й способ в данном случае предпочтительнее, так как здесь для определения вхождения буквы в текст достаточно однократного использования оператора IF, тогда как в первом случае для этого используется многократное применение того же оператора IF в операторе цикла FOR.