Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
TA / 1.3 Структуры данных.doc
Скачиваний:
24
Добавлен:
14.04.2015
Размер:
198.14 Кб
Скачать

1.3.2. Представление множеств.

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

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

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

Другой способ представления множества отличный от представления его в виде списка, - представление в виде двоичного (битового) вектора. Пусть U - универсальное множество (т.е. рассматриваемые множества являются его подмножествами), состоящее из n элементов. Линейно упорядочим его. Подмножество S U представляется в виде вектора Vs из n битов, такого, что i-й разряд в Vsравен 1 тогда и только тогда, когда i-й элемент множества U принадлежит S. Будем называть Vsхарактеристическим векторомдля S.

Представление в виде двоичного вектора удобно тем, что можно определить принадлежность i-го элемента множества U данному множеству за время, не зависящее от размера данного множества. Более того, основные операции над множествами, такие, как обьединение и пересечение можно осуществлять как операции над двоичными векторами.

Если мы не хотим считать операции над двоичными векторами первичными (т.е. вы-полняемыми за единицу времени), то можно с таким же успехом вместо характеристического вектора определить массив А,для которого А[i]=1 тогда и только тогда, когда i-й элемент множества U принадлежит S. При таком представлении все еще легко выяснить, принадлежит ли данный элемент данному множеству. Недостаток этого представления в том, что объединение и пересечение занимает время, пропорциональное |U|, а не размерам рассматриваемых множеств. Подобно этому память, требуемая для крайнего множества S, пропорциональна |U|, a не |S|.

1.3.3. Графы и их представление

Известны несколько представлений графа G=(V,E). Один из них - матрица смежностей, т.е. матрица А размера , состоящая из 0 и 1, в которой A[i,j]=1 тогда и только тогда,

когда есть ребро из узла i в узел j. Представление в виде матрицы смежности удобно для тех алгоритмов на графах, которым часто нужно знать есть ли в графе данное ребро, ибо время,

необходимое для определения наличия ребра, фиксировано и не зависит от |V| и |E|. Основной недостаток применения матрицы смежностей заключается в том, что она занимает память |V|2даже тогда, когда граф содержит только О(|V|) ребер. Уже начальное заполнение матрицы смежностей посредством "естественной" процедуры требует времени О(|V|2), что сводит на нет алгоритмы сложности О(|V|) при работе с графами, содержащими лишь О(|V|)

ребер. Поэтому алгоритмы, сложности О(|V|), основанные на работе с матрицей смежностей встречаются редко.

Интересной альтернативой является представление строк и(или) столбцов матрицы смежностей в виде двоичных векторов. Такое представление может способствовать значительной эффективности алгоритмов на графах.

Еще одно представление графа - с помощью списка. Списком смежностей для узла V называется список всех узлов W, смежных с V. Граф можно представить с помощью |V| списков смежностей, по одному для каждого узла.

А)

Б)

1

2

3

4

1

0

1

0

1

2

0

0

1

0

3

0

0

0

0

4

0

1

1

0


Г)

END NEXT

1

--

5

2

--

7

3

--

0

4

--

8

5

2

6

6

4

0

7

3

0

8

2

9

9

3

0

В)

УЗЕЛ 1

2

4

0

УЗЕЛ 2

3

0

УЗЕЛ 3

Пустой список

УЗЕЛ 4

2

3

0

УЗЛЫ

РЕБРА

Рис.3.7. Ориентированный граф и его представления:

а) орграф;

б) матрица смежностей;

в) списки смежностей;

г) табличное представление списков смежностей.

Пример 2. На рис.3.7.а изображен орграф, содержащий четыре узла, а на рис.3.7,б - его матрица смежностей. На рис.3.7,в показана четыре списка смежностей, по одному для каждого узла. Например, из узла 1 в узла 2 и 4 идут ребра, так что список смежностей для 1 содержит компоненты 2 и 4, связанные в смысле рис.1.

Табличное представление списка смежностей приведено на рис.3.7,г. Каждая из первых четырех ячеек в массиве NEXT содержит указатель на первый узел списка смежностей, а именно NEXT[i] указатель на первый узел списка смежностей для узла i.

Заметим, что NEXT[3]=0, поскольку в списке смежностей для узла 3 нет узлов. Остальные составляющие массива NEXT представляют ребра графа. Массив END содержит узлы из списков смежностей. Таким образом, список смежностей узла 1 начинается в ячейке 5, ибо NEXT[1]=5, END[5]=2; это показывает, что есть ребро (1,2). Равенства NEXT[5]=6 и END[6]=4 означают, что есть ребро (1,4), а NEXT[6]=0, что больше нет ребер, начинающихся в 1.

Заметим, что представление графа в виде списков смежностей требует памяти порядка |V|+|E|. Таким представлением часто пользуются, если |E|<<|V|2.

Если граф неориентирован, то каждое ребро (v,w) представляется дважды: один раз в списке смежностей для v и один раз в списке смежностей для w. В этом случае можно добавить новый массив, называемый CON, чтобы корректировать оба экземпляра неориен-тированного ребра. Таким образом, если i-ая ячейка, соответствующая узлу w в списке смежностей для v, то CON[i]- ячейка, соответствующая узлу v в списке смежностей для w.

Если мы хотим с удобством удалять ребра из неориентированного графа, то списки смежностей можно вводить дважды ( как описано в разделе 1.3.1.). Это обычно бывает нужно потому, что даже если удалять всегда ребро (v, w), стоящем первым в списке смежностей узла v, все равно может оказаться, что ребро, идущее в обратном направлении, стоит в середине списка смежностей узла w. Чтобы быстро удалить ребро (v, w) из списка смежностей для w, надо уметь быстро находить ячейку, содержащую предыдущее ребро в этом списке смежностей.

Полезность характеристических векторов вытекает из их компактности, существования простого отношения между i и адресом и i-го разряда и возможности при таком представлении очень легко исключать элементы.

Направленный характеристический вектор(ХВ) начального сегмента последовательности простых чисел имеет вид:

Si 1 2 3 4 5 6 7 8 9 10

ХВ для простых чисел 0 1 1 0 1 0 1 0 0 0

Главное неудобство ХВ состоит в том, что они неэкономичны. Исключением составляют "плотные" подпоследовательности последовательностей S1, S2, S3,... .Кроме того, их трудно использовать, если не существует простого соотношения между i и Si. Если такое соотношение сложное, то использование ХВ может быть очень не экономичным в смысле времени обработки. Если последовательности недостаточно плотные, то значительным может оказаться объем памяти.

Неудобство включения исключения элементов при последовательном распределении происходит из-за того, что порядок следования элементов задается неявно требованием, чтобы смежные элементы последовательности находились в смежных ячейках памяти. В результате многие элементы последовательности во время включения или исключения должны передвигаться. При связанном распределении последовательности (связанном списке) каждому Siпоставлен в соответствие указатель Pi, отмечающий ячейку, в которой записан элемент Si+1 и указатель на следующий за ним элемент.

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

С помощью связанных распределений мы добились большей гибкости, но потеряли некоторую информацию. При последовательном представлении фиксированное соотношение между i и ячейкой Siпозволяет иметь быстрый и прямой доступ к любому элементу последовательности. В связанном распределении такого соотношения не существует и доступ ко всем элементам последовательности, кроме первого, не является прямым и эффективным. Например, при последовательном представлении, если длина последовательности задана, то легко можно найти ее срединный элемент, это же самое труднее сделать, если последовательность задается заданным списком. Кроме того, приходится тратить на указатели Pi.

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

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

Еще большая гибкость достигается, если использовать дважды связанный список, когда каждый элемент Siпоследовательности вместо одного имеет два связанных с ним указателя на элементы Si-1 и Si+1.

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