Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АиПА / Лекции / 6_Комбинаторные задачи и вычисл на множествах.doc
Скачиваний:
16
Добавлен:
07.02.2016
Размер:
150.53 Кб
Скачать

2. Набор операций для множеств

Набор операций называют функционально полным, если он позволяет реализовать любой алгоритм вычислений. Выбор функционально полного набора операций не является однозначным. Следующий вариант такого выбора хотя и является избыточным, но удобным для вычислений:

- операция проверки принадлежности объекта данному множеству;

- операция включения нового элемента множества;

- операция исключения элемента из множества;

- операция объединения;

- операция пересечения;

- операция дополнения.

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

Результатом выполнения операции xA является логическое значение "Истина", если x принадлежит множеству A и значение "Ложь", если нет.

Включение

Операция обозначается как A+x или Ax , результатом является множество, в которое добавлен элемент x.

Исключение

Операция обозначается как A - x или A \ x . Результатом формируется путем исключения x из множества A. Если xA, результатом является множество A.

Объединение

Операция обозначается как AB. Результатом является множество, в которое включены все элементы из A и из B: AB = {x | xA или xB}.

Пересечение

Операция обозначается как AB. Результатом является множество, в которое включены только те элементы, которые принадлежат множеству A и, в то же время, множеству B:

AB = {x | xA и xB}.

Дополнение

Операция обозначается как A. Результатом является множество, в которое включены те элементы универсума, которые не принадлежат A: A = {x | xU и xA }. Эта операция определена только лишь в том случае, когда задан универсум.

3. Алгоритмы выполнения основных операций над множествами и их эффективность

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

Множество представлено битовым вектором

Проверка отношения xA . Под А будем понимать заданное множество и, в то же время, бинарный код этого множества. Эта операция сводится к считыванию из битового вектора значения бита номер x. Обозначим его через qx.

Пусть M = |U| . В качестве массива-носителя B бит. вектора выберем массив с элементами типа unsigned short (16 бит). Размер n массива B будет равным:

m = M/16+1 . (1)

Определим константу bit:

const unsigned short bit = 0x8000;

Она содержит единственный единичный бит в первой слева позиции 16-битового значения. Вычисление qx сводится к выполнению след. операций:

j=i/16; k=i%16;

qx = B[j] & (bit>>k);

Отсюда время выполнения этой операции равно: t = Const .

Это время не зависит ни от размера множества А, ни от размера универсума U.

Множество представлено одномерным массивом

Проверка отношения xA. Значение x поочередно сравнивается с элементами мн-ва A. Отсюда:

t = Const ∙n .

где n = |A| .

Множество представлено упорядоченным массивом

Использование алгоритма бинарного поиска дает:

t = Const ∙log(n) .

Включение

Множество представлено битовым вектором

Рассмотрим алгоритм включения элемента x в множество A, т.е. алгоритм выполнения операции A+x , где А – множество, x – добавляемый элемент. Операция сводится к установке бита с номером, равным x, в 1. Вычисления сводятся к выполнению след. операций:

j=i/16; k=i%16;

qx = B[j] || (bit>>k);

Отсюда время выполнения этой операции также равно: t = Const .

Множество представлено одномерным массивом

Операция A+x . Включаемый элемент x вносится в мн-во A в том случае, если он там не содержится. Отсюда имеем:

t = Const ∙n .

Множество представлено упорядоченным массивом

Эта операция содержит два шага:

- проверить, содержится ли заданное x в мн-ве А,

- если содержится, то вставить его в А, не нарушая порядка.

Определяющим (более медленным) является второй шаг. Для времени имеем:

t = Const ∙n .

Исключение

Множество представлено битовым вектором

Исключение элемента x из множества A сводится к установке бита с номером , в 0. Вычисления сводятся к выполнению след. операций:

bit = ~ (bit>>k);

j = i/16; k = i % 16;

qx = B[j] & bit;

Отсюда время выполнения этой операции также равно: t = Const .

Множество представлено одномерным массивом

Операция A-x может быть реализована такими операторами:

for (i = 0; i < n; i++) if (x == A[i]) break;

for (k = i; k < n-1; k++) A[i] = A[i+1];

Время выполнения обоих циклов будет равно:

t = c1n1+c2n2 ,

где c1 - время выполнения операции сравнения, c2 - время выполнения операции присваивания (пересылки), n1 – к-во итераций первого цикла, n2 – к-во итераций второго цикла. Пусть c = max(c1,c2), тогда, учитывая, что n = n1+n2, получаем:

t ≤ Constn .

Множество представлено упорядоченным массивом

Алгоритм такой же, как и для представления мн-ва неупорядоченным массивом. Для снижения времени можно использовать алгоритм бинарного поиска, однако порядок алгоритма остается таким же:

t ≤ Constn .

Объединение

Множество представлено битовым вектором

Определение операции объединения: AB = { x | xA или xB } .

Операция сводится к поэлементному выполнению операции дизъюнкции над парами соответствующих битов. Реализовать это можно следующим образом:

for (i = 0; i < m ;i++) C[i] = A[i] || B[i];

Здесь символы A,B,C используются как имена множеств и, в то же время, как имена соответствующих массивов-носителей.

Т.к. m и N связаны линейным соотношением (1), то при достаточно больших N будем иметь:

t = Const ∙N .

Множество представлено одномерным массивом

Операция AB. Пусть nA = |A| , nB = |B|. Данную операцию можно рассматривать как последовательность операций включения: для каждого элемента мн-ва В необходимо выполнить операцию вкючения его в м-во А. Т.к. операция включения требует линейного времени, имеем:

t ≤ ConstnAnB .

Множество представлено упорядоченным массивом

Можно использовать идею алгоритма слияния, которая используется для сортировки. Тогда упорядоченность массивов, представляющих множества, дает алгоритм с временем:

t = Const (nA+nB) ,

т.е. имеем линейный по времени алгоритм.

Пересечение

Множество представлено битовым вектором

AB = { x | xA и xB } .

Реализация этой операции выглядит так:

for (i = 0; i < m; i++) C[i] = A[i] & B[i];

и время выполнения этой операции такое же:

t = Const ∙N .

Множество представлено одномерным массивом

Операция AB. Здесь ситуация похожая: для каждого элемента мн-ва А необходимо проверить принадлежность его к мн-ву В. Отсюда:

t ≤ ConstnAnB .

Множество представлено упорядоченным массивом

Для пересечения легко строится алгоритм со временем:

t = Const (nA+nB) ,

Дополнение

Множество представлено битовым вектором

I ─ A

Алгоритм выполнения этой операции:

for (i = 0; i < m; i++) B[i] = ~ A[i];

И время равно

t = Const ∙N .

Множество представлено одномерным массивом

Для получения результата необходимо из универсума поочередно извлечь все элементы мн-ва А. Отсюда получаем: t = ConstnN .

Множество представлено упорядоченным массивом

Упорядоченность массивов-носителей не улучшает время выполнения этой операции:

t = Const ∙n∙N .

Эффективность выполнения операций над множествами для различных реализаций

Указаны оценки времени выполнения алгоритма в среднем

Битовый вектор

Не упорядоч. мн-во

Упорядоч. мн-во

xA ?

(1)

(nA)

(log(nA))

A + x

(1)

(nA)

(nA)

A – x

(1)

(nA)

(nA)

A  B

(N)

(nA∙nB)

(nA+nB)

А  В

(N)

(nA∙nB)

(nA+nB)

A

(N)

(nA∙N)

(N)

где n - число элементов множества X.