`
Читать книги » Книги » Компьютеры и Интернет » Программирование » Грокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих - Адитья Бхаргава

Грокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих - Адитья Бхаргава

1 ... 25 26 27 28 29 ... 46 ВПЕРЕД
Перейти на страницу:
стоимостей.

Теперь найдем узел с наименьшей стоимостью и обновим стоимости его соседей. В этом случае постер оказывается узлом с наименьшей стоимостью. Итак, в соответствии с алгоритмом Дейкстры, к постеру невозможно перейти более дешевым способом, чем с оплатой $0 (а вы знаете, что это неверно!) Как бы то ни было, обновим стоимости его соседей.

Получается, что теперь стоимость барабана составляет $35.

Перейдем к следующему по стоимости узлу, который еще не был обработан.

Обновим стоимости его соседей.

Узел «постер» уже был обработан, однако вы обновляете его стоимость. Это очень тревожный признак — обработка узла означает, что к нему невозможно добраться с меньшими затратами. Но вы только что нашли более дешевый путь к постеру! У барабана соседей нет, поэтому работа алгоритма завершена. Ниже приведены итоговые стоимости.

Чтобы добраться до барабанов, Раме потребовалось $35. Вы знаете, что существует путь, который стоит всего $33, но алгоритм Дейкстры его не находит. Алгоритм Дейкстры предположил, что, поскольку вы обрабатываете узел «постер», к этому узлу невозможно добраться быстрее. Это предположение работает только в том случае, если ребер с отрицательным весом не существует. Следовательно, использование алгоритма Дейкстры с графом, содержащим ребра с отрицательным весом, невозможно. Если вы хотите найти кратчайший путь в графе, содержащем ребра с отрицательным весом, для этого существует специальный алгоритм, называемый алгоритмом Беллмана—Форда. Рассмотрение этого алгоритма выходит за рамки этой книги, но вы сможете найти хорошие описания в Интернете.

Реализация

Посмотрим, как алгоритм Дейкстры реализуется в программном коде. Ниже изображен граф, который будет использоваться в этом примере.

Для реализации этого примера понадобятся три хеш-таблицы.

Хеш-таблицы стоимостей и родителей будут обновляться по ходу работы алгоритма. Сначала необходимо реализовать граф. Как и в главе 6, для этого будет использована хеш-таблица:

graph = {}

В предыдущей главе все соседи узла были сохранены в хеш-таблице:

graph["you"] = ["alice", "bob", "claire"]

Но на этот раз необходимо сохранить как соседей, так и стоимость перехода к соседу. Предположим, у начального узла есть два соседа, A и B.

Как представить веса этих ребер? Почему бы не воспользоваться другой хеш-таблицей?

graph["start"] = {}

graph["start"]["a"] = 6

graph["start"]["b"] = 2

Итак, graph["start"] является хеш-таблицей. Для получения всех соседей начального узла можно воспользоваться следующим выражением:

>>> print graph["start"].keys()

["a", "b"]

Одно ребро ведет из начального узла в A, а другое — из начального узла в B. А если вы захотите узнать веса этих ребер?

>>> print graph["start"]["a"]

2

>>> print graph["start"]["b"]

6

Включим в граф остальные узлы и их соседей:

graph["a"] = {}

graph["a"]["fin"] = 1

graph["b"] = {}

graph["b"]["a"] = 3

graph["b"]["fin"] = 5

graph["fin"] = {}  У конечного узла нет соседей

Полная хеш-таблица графа выглядит так:

Также понадобится хеш-таблица для хранения стоимостей всех узлов.

Стоимость узла определяет, сколько времени потребуется для перехода к этому узлу от начального узла. Вы знаете, что переход от начального узла к узлу B занимает 2 минуты. Вы знаете, что для перехода к узлу A требуется 6 минут (хотя, возможно, вы найдете более быстрый путь). Вы не знаете, сколько времени потребуется для достижения конечного узла. Если стоимость еще неизвестна, она считается бесконечной. Можно ли представить бесконечность в Python? Оказывается, можно:

infinity = float("inf")

Код создания таблицы стоимостей costs:

infinity = float("inf")

costs = {}

costs["a"] = 6

costs["b"] = 2

costs["fin"] = infinity

Для родителей также создается отдельная таблица:

Код создания хеш-таблицы родителей:

parents = {}

parents["a"] = "start"

parents["b"] = "start"

parents["fin"] = None

Наконец, вам нужен массив для отслеживания всех уже обработанных узлов, так как один узел не должен обрабатываться многократно:

processed = []

На этом подготовка завершается. Теперь обратимся к алгоритму.

Сначала я приведу код, а потом мы разберем его более подробно.

node = find_lowest_cost_node(costs)   Найти узел с наименьшей стои­мостью среди необработанных

while node is not None:  Если обработаны все узлы, цикл while завершен

    cost = costs[node]

    neighbors = graph[node]

    for n in neighbors.keys():    Перебрать всех соседей текущего узла

        new_cost = cost + neighbors[n]

        if costs[n] > new_cost:  Если к соседу можно быстрее добраться через текущий узел…

            costs[n] = new_cost    …обновить стоимость для этого узла

            parents[n] = node  Этот узел становится новым родителем для соседа

    processed.append(node)     Узел помечается как обработанный

    node = find_lowest_cost_node(costs)   Найти следующий узел для обработки и повторить цикл

Так выглядит алгоритм Дейкстры на языке Python! Код функции будет приведен далее, а пока рассмотрим пример использования алгоритма в действии.

Найти узел с наименьшей стоимостью.

Получить стоимость и соседей этого узла.

1 ... 25 26 27 28 29 ... 46 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Грокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих - Адитья Бхаргава, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)