Опубликован: 26.09.2006 | Доступ: свободный | Студентов: 1741 / 445 | Оценка: 4.25 / 4.12 | Длительность: 17:09:00
ISBN: 978-5-9556-0066-6
Специальности: Программист, Математик
Лекция 2:

Списки

< Лекция 1 || Лекция 2: 123456 || Лекция 3 >

Деревья и графы

Деревья находят широкое применение при проектировании алгоритмов и, в частности, структур данных. Отсылая читателя к литературе по теории графов, мы будем пользоваться такими понятиями, как узел, ребро, лист, потомок, сын, левый потомок, правый потомок, предок, отец, корень, ветвь и другие. Регулярным деревом назовем дерево, в котором фиксировано максимально возможное (как правило, небольшое) число потомков для каждого из его узлов. В частности, если число потомков для каждого узла не больше двух, то дерево называется бинарным, если не более трех — тернарным. Если это число может равняться только двум или трем, то дерево называется ( 23 )-деревом.

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

Так, узлы бинарного корневого дерева можно представлять записями вида

\eq*{
[{\rm Element}, {\rm Left}, {\rm Right}],
}
где {\rm Element} представляет связанную с узлом прикладную информацию, {\rm Left} — позицию его левого потомка, а {\rm Right} — позицию правого потомка. Само дерево в таком случае можно представить позицией его корня. Если в алгоритме необходимо продвижение от узла к предку, то узлы бинарного корневого дерева можно представлять записями вида
\eq*{
[{\rm Element}, {\rm Left}, {\rm Right}, {\rm Father}],
}
где {\rm Father} — позиция предка рассматриваемого узла.

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

Для регулярных деревьев более экономным по памяти может оказаться представление с помощью массива. Рассмотрим этот прием на примере бинарного дерева. Значения индексов массива отождествляются с узлами дерева, пронумерованными так, что корень получает номер 1, а потомки узла c номером i получают номера 2i и 2i +
1. При таком представлении предок узла с номером i будет иметь номер i
\mathop{\rm div}\nolimits 2 (частное от деления i на 2). Аналогично можно представить тернарное и другие регулярные деревья.

Остановимся вкратце на представлении графов общего вида. Обыкновенный граф с n вершинами часто представляют матрицей смежности, то есть матрицей размером n\x n, в которой элемент, расположенный в i -й строке и j -м столбце, равен 1, если вершины графа с номерами i, j соединены ребром, и равен 0, если такого ребра нет. Если граф не ориентирован, то его матрица смежности симметрична и можно ограничиться хранением ее треугольной части.

Матричный способ представления может оказаться неэкономным с точки зрения использования памяти, если граф разрежен. Так, например, известно, что число ребер связного планарного графа с n вершинами не превосходит величины ( 3n - 6 ) при n \ge 3, то есть оценивается величиной O(n), а не как в общем случае O(n^2). Представлять такие графы матрицей смежности, как правило, нецелесообразно.

Другой способ представления графа — это список или массив пар вершин, соответствующих ребрам. При таком способе, если граф не ориентирован, то из двух возможных пар ( i, j ) и ( j, i ) целесообразно хранить только одну, например ту, у которой первая компонента меньше второй.

Еще один способ, часто имеющий преимущества перед названными выше, — это представление графа массивом или списком списков (рис. 2.7).

Представление графа комбинацией списков: множество вершин представлено списком узлов, к каждому из которых справа подцеплен список смежных с ним вершин

Рис. 2.7. Представление графа комбинацией списков: множество вершин представлено списком узлов, к каждому из которых справа подцеплен список смежных с ним вершин

А именно, для каждой вершины организуется список смежных с ней вершин. В этом случае легко осуществляется доступ к окрестностям вершин. Примерно такого же эффекта можно достичь, представляя граф с помощью двух массивов: {\rm inf} [1 \ldots m] и {\rm adr} [1\ldots n + 1)], где m — число ребер графа. Массив {\rm adr} назовем адресным, а {\rm
inf} — информационным. В информационном массиве вначале перечисляются номера вершин, смежных с первой вершиной, затем — со второй и так далее. В адресном массиве указываются номера позиций информационного массива так, чтобы для каждой вершины i по ним можно было находить фрагменты массива {\rm
inf}, в которых записаны номера вершин, смежных с этой вершиной. Например, {\rm adr}[i] может хранить позицию, с которой начинаются в массиве {\rm inf} вершины, смежные с i -й, при этом {\rm adr}[n + 1] — первая позиция за пределами массива {\rm inf}. В таком случае, если нам требуется с каждой вершиной j из окрестности вершины i выполнить оператор S(j), то можно сделать это с помощью оператора цикла:

\eq*{
for k := {\rm adr}[i]\ to\ {\rm adr} [i + 1] - 1\ \t{do}
S({\rm inf}[k]).
}

Заметим, что если граф не ориентирован, то каждое ребро ( i, j ) будет представлено дважды: один раз в последовательности вершин, смежных с вершиной i, а второй раз — в последовательности вершин, смежных с вершиной j. Но эта избыточность часто бывает полезна с точки зрения времени выполнения операций над окрестностями вершин графа. Как недостаток такого представления графа, можно отметить неудобство при динамической модификации графа, например, добавление к графу ребра может потребовать большого количества пересылок в массиве \rm inf. Этого недостатка лишен способ представления графа, показанный на рис. 2.7.

< Лекция 1 || Лекция 2: 123456 || Лекция 3 >
Антон Сиротинкин
Антон Сиротинкин

на стр 6, лекции 3, Очевидно "Ck <= модуль(Gk(е))*b(k+1)" (1) - , подскажите что значит "модуль" и почему это очевидно...