Иллюстрированный самоучитель по Turbo Pascal

Множества

В отличие от операций + и -, реализующих аналогичные действия над двумя множествами, процедуры оптимизированы для работы с одиночными элементами множеcтва и поэтому отличаются высокой скоростью выполнения.

В примере 4.1, иллюстрирующем приемы работы с множествами, реализуется алгоритм выделения из первой сотни натуральных чисел всех простых чисел. В его основе лежит прием, известный под названием "решето Эратосфена". В соответствии с этим алгоритмом вначале формируется множество BEGINSET, состоящее из всех целых чисел в диапазоне от 2 до N. В множество PRIMERSET (оно будет содержать искомые простые числа) помещается 1. Затем циклически повторяются следующие действия:

  • взять из BEGINSET первое входящее в него число NEXT и поместить его в PRIMERSET;
  • удалить из BEGINSET число NEXT и все другие числа, кратные ему, т.е.2*NEXT, 3*NEXT и т.д.

Цикл повторяется до тех пор, пока множество BEGINSET не станет пустым.

Эту программу нельзя использовать для произвольного N, так как в любом множестве не может быть больше 256 элементов.

Пример 4.1.

Program Primer_numbers_detect;
{Выделение всех простых чисел из первых N целых}
const
N = 255; {Количество элементов исходного множества}
type
SetOfNumber = set of 1..N;
var
n1,next,i: Word; {Вспомогательные переменные}
BeginSet, {Исходное множество}
PrimerSet: SetOfNumber; {Множество простых чисел}.
begin
BeginSet: = [2..N]; {Создаем исходное множество}
PrimerSet: = [1]; {Первое простое число}
next: = 2; {Следующее простое число}
while BeginSet <> [] do {Начало основного цикла}
begin
n1: = next; {n1-число,кратное очередному простому (next)}
{Цикл удаления из исходного множества непростых чисел:}
while n1 <= N do
begin
Exclude(BeginSet,nl);
n1: = n1+next {Следующее кратное}
end; {Конец цикла удаления}
Include(PrimerSet,next);
{Получаем следующее простое, которое есть первое невычеркнутое из исходного множества}
repeat
inc(next)
until (next in BeginSet) or (next > N)
end; {Конец основного цикла}
{Выводим результат:}
for i: = 1 to N do
if i in PrimerSet then Write(i:8);
WriteLn
END.

Перед тем как закончить рассмотрение множеств полезно провести небольшой эксперимент. Измените описание типа SETOFNUMBER следующим образом:

type
SetOf Number = set of 1.. 1;

И еще раз запустите программу из предыдущего примера. На экран будет выведено:

1 3 5 7

Множества BeginSet и PrimerSet состоят теперь из одного элемента, а программа сумела поместить в них не менее семи! Секрет этого прост: внутреннее устройство множества таково, что каждому его элементу ставится в соответствие один двоичный разряд (один бит); если элемент включен во множество, соответствующий разряд имеет значение 1, в противном случае – 0. Минимальной единицей памяти является один байт, содержащий 8 бит. Компилятор выделил множествам по одному байту, в результате мощность каждого из них стала равна 8 элементов. Максимальная мощность множества – 256 элементов. Для таких множеств компилятор выделяет по 16 смежных байт.

И еще один эксперимент: измените диапазон базового типа на 1.256. Хотя мощность этого типа составляет 256 элементов, при попытке компиляции программы компилятор сообщит:

Error 23: Set base type out of range.
(Ошибка 23: Базовый тип множества выходит за допустимые границы.)

Компилятор разрешает использовать в качестве базового типа целочисленный тип-диапазон с минимальной границей 0 и максимальной 255 или любой перечисляемый тип не более чем с 256 элементами (максимальная мощность перечисляемого типа – 5536 элементов).

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.