Содержание
Список рёбер
Этот способ задания графов наиболее удобен для внешнего представления входных данных. Пусть каждая строка входного файла содержит информацию об одном ребре (дуге):
<номер_начальной_вершины> <номер_конечной_вершины> [<вес_ребра>]
В качестве примера приведём списки ребёр (дуг), задающие те же три графа с рис. 11.5, рис. 11.6 и рис. 11.7 (см. рис. 11.9).
Таблица 11.9. Примеры списков рёбер (дуг)
a b a c b c b d c d c f f d b f | 1 2 1 4 3 1 3 2 3 5 4 3 | a b 1 a c 10 b c 2 b d 10 c d 3 |
Если задаётся ориентированный граф, то номера вершин понимаются как упорядоченная пара, а если граф неориентированный — как неупорядоченная.
Списки смежности
Этот способ задания графов подразумевает, что для каждой вершины будет указан список всех смежных с нею вершин (для орграфа — список вершин, являющихся концами исходящих дуг). Конкретный формат входного файла, содержащего списки смежности, необходимо обговорить отдельно. Например, в нашем случае начальная вершина отделена от списка смежности двоеточием:
<номер_начальной_вершины>: <номера_смежных_вершин>
Наиболее естественно применять этот способ для задания орграфов, однако и для остальных вариантов он тоже подходит.
В качестве примера приведём списки смежности, задающие всё те же три графа, изображённые на рис. 11.5, рис. 11.6 и рис. 11.7 (см. рис. 11.10).
Таблица 11.10. Примеры списков смежности
a: b c b: c d f c: d f d: f | 1: 2 4 3: 1 2 5 4: 3 | b: a 1 c 2 d 10 c: a 10 d 3 |
Иерархический список
Собственно, этот способ представления графов является всего лишь внутренней реализацией списка смежности: в одном линейном списке содержатся номера «начальных вершин», а в остальных — номера смежных вершин или указатели на эти вершины. В качестве примера (см. рис. 11.11) приведём иерархический список, задающий орграф, изображённый на рис. 11.6.
/11%2D11.gif)
Рис. 11.11. Пример иерархического списка
uk_duga = ^duga;
vershina = record
number : Integer;
sled_vershina : uk_versh;
spisok_dug : uk_duga
end;
duga = record
konec_dugi : uk_versh;
sled_duga : uk_duga;
end;
Очевидное преимущество такого способа представления графов заключается в экономичном использовании памяти. И даже небольшая избыточность данных, к которой приходится прибегать в случае неориентированного графа, задавая каждое ребро как две дуги, искупается гибкостью всей структуры, что особенно удобно при необходимости частых перестроений в процессе работы программы.
Если в приведённые описания типов данных добавить поля, которые могли бы хранить веса вершин и дуг, то таким же способом можно задавать и взвешенные графы (орграфы).
Деревья
Дерево — это частный случай графа, наиболее широко применяемый в программировании.
Основные определения
Существует довольно много равносильных определений деревьев, вот лишь некоторые из них.
- Дерево — это связный граф без циклов.
- Дерево — это связный граф, в котором при N вершинах всегда ровно N-1 ребро.
- Дерево — это граф, между любыми двумя вершинами которого существует ровно один путь.
Аналогичным образом определяется и ориентированное дерево — как орграф, в котором между любыми двумя вершинами существует не более одного пути.
Таблица 11.4. Примеры деревьев
| Дерево | Вершины | Рёбра (дуги) |
|---|---|---|
| Армия | Солдаты и офицеры | Иерархия (командир — подчинённый) |
| Династия (родословная по мужской линии) | Монархи | Отношение «отец — сын» |
/11%2D12.gif)
Рис. 11.12. Корневое дерево высоты 3
Мы будем изучать и использовать только один частный случай ориентированных деревьев — корневые деревья (см. рис. 11.12).
Корневое дерево — это ориентированное дерево, в котором можно выделить вершины трёх видов: корень, листья (другое их название: терминальные вершины) и остальные вершины (нетерминальные); причём должны выполняться два обязательных условия:
- из листьев не выходит ни одна дуга; из других вершин может выходить сколько угодно дуг;
- в корень не заходит ни одна дуга; во все остальные вершины заходит ровно по одной дуге.
Традиционно в математике и в родственных ей науках (в том числе и в теоретическом программировании) деревья «растут» вниз головой: это делается просто для удобства наращивания листьев в случае необходимости. Таким образом, на рисунках корень дерева оказывается самой верхней вершиной, а листья — самыми нижними.
Предок вершины v — это вершина, из которой исходит дуга, заходящая в вершину v. Потомок вершины v — это вершина, в которую заходит дуга, исходящая из вершины v. В этих терминах можно дать другие определения понятиям корень и лист: у корня нет предков, у листа нет потомков.
Бинарное дерево — это корневое дерево, каждая вершина которого имеет не более двух потомков. В таком случае иногда говорят о левом потомке и правом потомке для текущей вершины.
Высота корневого дерева — это максимальное количество дуг, отделяющих листья от корня. Если дерево не взвешенное, то его высота — это просто расстояние от корня до самого удалённого листа.
И в заключение мы приведём определение, связывающее произвольные графы с деревьями более плотно.
Каркас графа — это дерево, полученное после выбрасывания из графа некоторых рёбер (см. рис. 11.13).
/11%2D13.gif)
Рис. 11.13. Каркас графа
Примером каркаса является (корневое) дерево кратчайших путей от некоторой выделенной вершины (она будет корнем каркаса) до всех остальных вершин графа.


::
::
::