Rambler's Top100

Скачать программы    Все программы автора

6.3. Множества.

Пусть T - некоторый тип. Существует много способов хранить (конечные) множества элементов типа T; выбор между ними определяется типом T и набором требуемых операций.

Подмножества множества {1..n}.

6.3.1. Используя память, пропорциональную n, хранить подмножества множества {1..n}.

Операции Число действий

Сделать пустым C*n

Проверить принадлежность C

Добавить C

Удалить С

Минимальный элемент C*n

Проверка пустоты C*n

Решение. Храним множество как array [1..n] of boolean.

6.3.2. То же, но проверка пустоты должна выполняться за время C.

Решение. Храним дополнительно количество элементов.

6.3.3. То же при следующих ограничениях на число действий:

Операции Число действий

Сделать пустым C*n

Проверить принадлежность C

Добавить C

Удалить C*n

Минимальный элемент C

Проверка пустоты C

Решение. Дополнительно храним минимальный элемент множества.

6.3.4. То же при следующих ограничениях на число действий:

Операции Число действий

Сделать пустым С*n

Проверить принадлежность С

Добавить С*n

Удалить С

Минимальный элемент С

Проверка пустоты C

Решение. Храним минимальный, а для каждого - следующий и предыдущий по величине.

Множества целых чисел.

В следующих задачах величина элементов множества не ограничена, но их количество не превосходит n.

6.3.5. Память C*n.

Операции Число действий

Сделать пустым C

Число элементов C

Проверить принадлежность C*n

Добавить новый

(заведомо отсутствующий) C

Удалить C*n

Минимальный элемент C*n

Взять какой-то элемент C

Решение. Множество представляем с помощью переменных a:array [1..n] of integer, k: 0..n; множество содержит k элементов a[1],...,a[k]; все они различны. По существу мы храним элементы множества в стеке (без повторений). С тем же успехом можно было бы воспользоваться очередью вместо стека.

6.3.6. Память C*n.

Операции Число действий

Сделать пустым C

Проверить пустоту C

Проверить принадлежность C*(log n)

Добавить С*n

Удалить C*n

Минимальный элемент С

Решение. См. решение предыдущей задачи с дополнительным условием a[1] < ... < a[k]. При проверке принадлежности используем двоичный поиск.

В следующей задаче полезно комбинировать разные способы.

6.3.7. Используя описанные способы представления множеств, найти все вершины ориентированного графа, доступные из данной по ребрам. (Вершины считаем числами 1..n.) Время не больше C * (общее число ребер, выходящих из доступных вершин).

Решение. (Другое решение смотри в главе о рекурсии.) Пусть num[i] - число ребер, выходящих из i, out[i][1], ..., out[i][num[i]] - вершины, куда ведут рёбра из вершины i.

procedure Доступные (i: integer);

| {напечатать все вершины, доступные из i, включая i}

| var X: подмножество 1..n;

| P: подмножество 1..n;

| q, v, w: 1..n;

| k: integer;

begin

| ...сделать X, P пустыми;

| writeln (i);

| ...добавить i к X, P;

| {(1) P = множество напечатанных вершин; P содержит i;

| (2) напечатаны только доступные из i вершины;

| (3) X - подмножество P;

| (4) все напечатанные вершины, из которых выходит

| ребро в ненапечатанную вершину, принадлежат X}

| while X непусто do begin

| | ...взять какой-нибудь элемент X в v;

| | for k := 1 to num [v] do begin

| | | w := out [v][k];

| | | if w не принадлежит P then begin

| | | | writeln (w);

| | | | добавить w в P;

| | | | добавить w в X;

| | | end;

| | end;

| end;

end;

Свойство (1) не нарушается, так как печать происходит одновременно с добавлением в P. Свойства (2): раз v было в X, то v доступно, поэтому w доступно. Свойство (3) очевидно. Свойство (4): мы удалили из X элемент v, но все вершины, куда из v идут ребра, перед этим напечатаны.

Оценка времени работы. Заметим, что изъятые из X элементы больше туда не добавляются, так как они в момент изъятия (и, следовательно, всегда позже) принадлежат P, а добавляются только элементы не из P. Поэтому тело цикла while для каждой доступной вершины выполняется не более, чем по разу, при этом тело цикла for выполняется столько раз, сколько из вершины выходит ребер.

Для X надо использовать представление со стеком или очередью (см. выше), для P - булевский массив.

6.3.8. Решить предыдущую задачу, если требуется, чтобы доступные вершины печатались в таком порядке: сначала заданная вершина, потом ее соседи, потом соседи соседей (еще не напечатанные) и т.д.

Указание. Так получится, если использовать очередь для хранения множества X в приведенном выше решении: докажите индукцией по k, что существует момент, в который напечатаны все вершины на расстоянии не больше k, а в очереди находятся все вершины, удаленные ровно на k.

Вверх

Белорусский рейтинг MyMinsk.com Сайты беларуси Регистр "ЗУБР" Каталог на TIGA.BY, а также  новости, работа, объявления, фото и многое другое Rambler's Top100 Белорусский каталог программ Faststart - рейтинг сайтов, каталог интернет ресурсов, счетчик посещаемос­ти Яндекс.Метрика
Hosted by uCoz