Добавил:
Лабы/курсовые по программированию (С++/Verilog HDL), Теория и Практика Помехоустойчивого Кодирования Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1сем Дагаев / f7e89f0dfd811ccc.ppt
Скачиваний:
18
Добавлен:
09.03.2022
Размер:
3.03 Mб
Скачать

Использование стека для обхода графа.

Граф:

2

 

Если в качестве промежуточной структуры

 

 

хранения при обходе использовать стек, то

1

 

3

получается обход в глубину.

 

1

5

8

7

6

4

3

2

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Можно также получить дерево обхода

5

 

6

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

 

 

 

или обратную дугу.

 

 

 

 

7

 

 

 

 

 

 

 

 

 

8

 

 

1

2

3

4

5

6

7

8

Стек:

 

 

3

4

6

1

7

5

5

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

 

 

 

 

 

8

 

 

 

 

 

 

 

 

 

Использование очереди для обхода графа.

Граф:

2

 

Если в качестве промежуточной структуры

 

 

хранения при обходе использовать очередь,

1

 

3

то получается обход в ширину.

 

 

1

2

4

 

5

3

6

7

8

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Можно также получить дерево обхода в ширину,

5

 

6

если отмечать каждую прямую дугу.

 

7

 

1

2

3

4

5

6

7

8

 

1 2 1 1 4 5 5

8 Очередь:

2

4

7

8

Поиск кратчайших путей в ненагруженном графе.

Граф:

 

Алгоритм обхода графа с помощью очереди

2

позволяет построить дерево кратчайших путей

 

 

 

из заданной вершины и вычислить их длины.

1

 

3

 

 

 

 

 

 

 

 

 

 

4

1

2

4

5

 

3

6

 

7

8

 

 

 

 

 

 

 

 

 

 

 

5

 

6

n

1 2 3 4 5 6 7 8

 

 

 

π

 

1

2

1

1

4

5

5

 

7

 

d

0

1

2

1

1

2

2

2

8 Очередь:

2

4

7

8

Программа обхода графа с использованием контейнера.

public static void traverseWithContainer(Graph g, GraphVisitor visitor, int start, ContainerFactory factory) {

// Инициализация

 

int n = g.vertices();

// Число вершин графа

Container container = factory.createContainer(n);

// Создание контейнера

container.push(start);

// Инициализация контейнера

boolean[] inQueue = new boolean[n];

 

boolean[] passed = new boolean[n];

 

inQueue[start] = true;

 

visitor.visitVertexIn(start);

 

while (!container.isEmpty()) {

int current = container.pull(); passed[current] = true; visitor.visitVertexOut(current);

for (Iterator arcs = g.adjacentArcs(current); arcs.hasNext(); ) { Graph.Arc arc = (Graph.Arc)arcs.next();

int end = arc.getTo(); if (passed[end])

visitor.visitArcBackward(current, arc); else {

visitor.visitArcForward(current, arc, inQueue[end]); if (!inQueue[end]) {

container.push(end); inQueue[end] = true; visitor.visitVertexIn(end);

}

}

}

}

}

Программа поиска кратчайших путей в ненагруженном графе.

public static void findMinPaths(Graph g,

// Исходный граф

int start,

// Стартовая вершина

final int[] tree,

// Результирующее дерево

final int[] dist)

// Массив расстояний

{

 

dist[start] = 0;

 

tree[start] = 0;

 

traverseWithContainer(g, new GraphVisitor() {

// Коррекция пути производится при первом проходе по дуге вперед public void visitArcForward(int from, Graph.Arc arc, boolean retArc) {

if (!retArc) {

int end = arc.getTo(); dist[end] = dist[from] + 1; tree[end] = from;

}

}

},

start, new QueueFactory());

}

Алгоритмы поиска кратчайших путей в нагруженном графе.

Кратчайший путь между двумя вершинами – это путь с минимальным суммарным весом составляющих этот путь ребер

Кратчайшие пути из вершины (10):

 

 

2

 

1

1

 

 

3

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

4

5

 

 

V

Длина

Путь через

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

 

2

 

 

3

 

 

1

3

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

1

 

 

 

2

2

 

10

3

 

5

8

 

 

 

9

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

1

 

4

 

 

 

2

 

 

 

 

4

6

2, 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

4

2

 

 

6

 

4

7

 

 

 

 

 

 

6

4

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7

8

2, 8 или 3, 6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

8

6

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9

7

2, 8

Кратчайший путь между двумя вершинами существует, если в графе нет цикла с суммарным отрицательным весом.

Алгоритм релаксации ребра при поиске кратчайших путей.

 

 

2

 

1

1

3

4

Пусть уже найдены оценки

 

 

 

 

 

 

 

 

2

4

 

5

3

кратчайших путей для вершин,

 

2

 

 

соединенных ребром.

 

 

 

 

 

 

 

 

 

 

5

 

 

6

 

 

 

 

 

 

 

 

 

 

d[8] = 6;

10

3

3

 

5

8

1

9

 

 

 

d[7] = 9

 

 

 

 

 

 

 

 

 

5

1

4

 

 

2

 

 

 

 

 

 

 

 

 

 

6

 

4

7

 

 

 

 

 

 

 

89

 

 

Релаксация ребра (u, v):

if (d[u] + w(u,v) < d[v]) d[v] = d[u] + w(u,v);

Релаксация ребра (7, 8):

Релаксация ребра (8, 7):

9 + 2 > 6

6 + 2 < 9 d[7] = 8

Инициализация:

 

d[start] = 0; d[i] = ∞

 

Последовательная релаксация ребер приведет к нахождению кратчайших путей. В каком порядке и сколько раз производить релаксацию ребер?

Алгоритм Дейкстры поиска кратчайших путей.

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

 

 

2

 

2

1

 

3

 

4

 

 

 

 

 

 

 

 

6

 

1

3

 

1

 

 

4

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

10

1

3

 

5

8

 

 

3

9

 

 

 

 

 

 

3

1

1

 

 

1

 

 

 

4

6 7

n

1

2

3

4

5

6

7

8

9

10

π

 

 

 

 

 

 

 

 

 

 

2

5

10

8

6

3

6

2

8

 

d

 

 

 

 

 

 

 

 

 

 

6

4

1

8

3

2

6

7

10

0

 

 

 

 

 

 

 

 

 

 

 

Очередь

3

5

2

7

1

8

4

9

Программа для реализации алгоритма Дейкстры поиска кратчайших путей.

public static void DijkstraPath(Graph g, int start, final int[] tree, final double[] dist) {

for (int i = 0; i < g.vertices(); i++) { dist[i] = Double.MAX_VALUE; } dist[start] = 0;

traverseWithContainer(g, new DepthVisitor() {

public void visitArcForward(int from, Graph.Arc arc, boolean retArc)

{

if (dist[from] + arc.getWeight() < dist[arc.getTo()]) { dist[arc.getTo()] = dist[from] + arc.getWeight(); tree[arc.getTo()] = from;

}

}

}, start, new SimplePrioQueueFactory(dist));

}

Время работы алгоритма (max): время обхода графа (n + m) плюс время на организацию работы очереди с приоритетами (n log n)

Кратчайшие пути в ориентированном графе

1.Если в ориентированном графе нет дуг с отрицательным весом, то алгоритм Дейкстры работает точно так же, как и в случае неориентированных графов.

2.Если в ориентированном графе нет циклов с отрицательным весом, то можно применить алгоритм Беллмана – Форда.

2

1

 

2 3 -3

2

4

-2

5

 

1

3

7 2

2

2

9

-1 3

2

3

2

2 6

 

-1

4

2

 

8

-1

n

1

2

3

4

5

6

7

8

9

 

 

 

 

 

 

 

 

 

 

π

3

4

8

 

4

8

5

9

7

 

 

 

 

 

 

 

 

 

 

d

1

2

2

0

-2

-1

-1

0

1

 

 

 

 

 

 

 

 

 

 

И так далее… В конце концов получится…

Соседние файлы в папке 1сем Дагаев