Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Class adjIterator






{

public:

adjlterator(const GRAPH &, int); Edge *beg(); Edge *nxt(); bool end();

}; };

Более приемлемая для клиентов альтернатива предусматривает объявление типа дан­ных Edge и, в условиях нашей реализации, манипулирование указателями на ребра. В про­грамме 20.1 содержатся подробности использования интерфейсов EDGE, GRAPH и ите­ратора АТД, который применяется для поддержки этого подхода. Для использования в других контекстах клиенты легко могут выполнить минимальные требования типа данных Edge, сохраняя при этом гибкость, позволяющую давать определения типов данных, от­ражающих специфику конкретных приложений. Предлагаемые нами реализации могут манипулировать указателями на ребра и использовать интерфейс с целью извлечения не-



Часть 5. Алгоритмы на графах


обходимой им информации из интерфейсов EDGE независимо от их представления. Про­грамма 20.2 представляет собой пример клиентской программы, которая использует этот интерфейс.

Программа 20.2. Пример клиентской функции обработки графа_______________________

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

template < class Graph, class Edge> vector < Edge *> edges(const Graph & G) { int E = 0;

vector < Edge *> a (G.E ());

for (int v = 0; v < G.V(); v++)

{

typename Graph:: adjIterator A(G, v);

for (Edge* e = A.beg();! A.end(); e = A.nxt())

if (e-> from(v)) a[E++] = e; }

return a; }

Программа 20.3. Класс взвешенного графа

(представление в виде матрицы смежности)___________________________________

Для насыщенных взвешенных графов мы используем матрицу указателей на данные типа Edge с указателем на ребро в v-u в строке v и столбце w. Для неориентированных графов мы устанавливаем другой указатель на ребро в строке w и столбце v. Нулевой указатель свидетельствует об отсутствии соответствующего ребра; когда мы удаляем ребро с помощью функции remove(), мы удаляем указатель на него. Рассматриваемая реализация не производит проверки на наличие параллельных ребер, в то же время клиенты могут для этой цели воспользоваться функцией edge.

template < class Edge> class DenseGRAPH { int Vcnt, Ecnt; bool digraph; vector < vector < Edge *> > ad j; public:

DenseGRAPH(int V, bool digraph = false): adj(V), Vcnt(V), Ecnt(O), digraph(digraph) { for (int i = 0; i < V; i++)

adj[i].assign(V, 0); }

int V() const { return Vcnt; } int E() const { return Ecnt; } bool directed() const { return digraph; } void insert(Edge *e)

{ int v = e-> v(), w = e-> w(); if (adj[v][w] == 0) Ecnt++; adj[v][w] =е;

if (! digraph) adj [w] [v] = e; }

void remove(Edge *e) { int v = e-> v(), w =e-> w(); if (adj[v][w]! = 0) Ecnt--; adj[v][w] - 0;


Глава 20. Минимальные остовные деревья



if (! digraph) adj[w][v] = 0; } Edge* edge (int v, int w) const

{ return adj[v][w]; } class adjIterator; friend class adjlterator; };

В алгоритмах тестирования и в базовых приложениях мы используем класс EDGE (ребро), имеющий два приватных элемента данных типа int и double, которые инициали­зируются аргументами конструктора и являются возвращаемыми значениями, соответ­ственно, функций-элементов v(), w() и wt() (см. упражнение 20.8). Во избежание распро­странения простых типов данных, на протяжении данной главы и главы 21 мы будем использовать для представления веса ребер тип данных double. В наших примерах в ка­честве весов ребер мы будем использовать вещественные числа из диапазона от 0 до 1. Это решение не противоречит различным альтернативам, которые могут понадобиться в приложениях, поскольку мы можем явно или неявно изменить веса таким образом, что­бы они соответствовали этой модели (см. упражнения 20.1 и 20.10.). Например, если ве­сами являются целые числа, меньшие некоторого известного максимального значения, то поделив значения весов на это максимальное значение, мы преобразуем их в веществен­ные числа, принимающие значения в диапазоне от 0 до 1.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.