RSS    

   Реферат: VB, MS Access, VC++, Delphi, Builder C++ принципы(технология), алгоритмы программирования

    ' Обратиться к непомеченным узлам.

    For Each link In Links

        ' Найти соседний узел.

        If link.Node1 Is Me Then

           Set node = link.Node2

        Else

           Set node = link.Node1

        End If

        ' Определить, требуется ли обращение к соседнему узлу.

        If Not node.Marked Then node.PreorderPrint

    Next link

End Sub

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

Если сеть является связной, то дерево будет обходить все узлы сети. Так как это дерево охватывает все узлы сети, то оно называется остовным деревом (spanning tree). На рис. 12.4 показана небольшая сеть с остовным деревом с корнем в узле A, которое изображено жирными линиями.

Можно использовать похожий подход с пометкой узлов для преобразования обхода дерева в ширину в сетевой алгоритм. Алгоритм обхода дерева начинается с помещения корневого узла в очередь. Затем первый узел удаляется из очереди, происходит обращение к узлу, и затем в конце очереди помещаются его дочерние узлы. Затем этот процесс повторяется до тех пор, пока очередь не опустеет.

======318

@Рис. 12.4. Остовное дерево

В алгоритме обхода сети нужно вначале убедиться, что узел не проверялся раньше или он уже не находится в очереди. Для этого мы помечаем каждый узел, который помещается в очередь. Сетевая версия этого алгоритма выглядит так:

       Пометить первый узел (который будет корнем остовного дерева) и добавить его в конец очереди.

       Повторять следующие шаги до тех пор, пока очередь не опустеет:

a)   Удалить из очереди первый узел и обратиться к нему.

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

Следующая процедура печатает список узлов сети в порядке обхода в ширину:

Public Sub BreadthFirstPrint(root As NetworkNode)

Dim queue As New Collection

Dim node As NetworkNode

Dim neighbor As NetworkNode

Dim link As NetworkLink

    ' Поместить корень в очередь.

    root.Marked = True

    queue.Add root

    ' Многократно помещать верхний элемент в очередь

    ' пока очередь не опустеет.

    Do While queue.Count > 0

        ' Выбрать следующий узел из очереди.

        Set node = queue.Item(1)

        queue.Remove 1

        ' Обратиться к узлу.

        Print node.Id

        ' Добавить в очередь все непомеченные соседние узлы.

        For Each link In node.Links

           ' Найти соседний узел.

           If link.Node1 Is Me Then

               Set neighbor = link.Node2

           Else

               Set neighbor = link.Node1

           End If

           ' Проверить, нужно ли обращение к соседнему узлу.

           If Not neighbor.Marked Then queue.Add neighbor

        Next link

    Loop

End Sub

Наименьшие остовные деревья

Если задана сеть с ценой связей, то наименьшим остовным деревом (minimal spanning tree) называется остовное дерево, в котором суммарная цена всех связей в дереве будет наименьшей. Наименьшее остовное дерево можно использовать, чтобы связать все узлы в сети путем с наименьшей ценой.

Например, предположим, что требуется разработать телефонную сеть, которая должна соединить шесть городов. Можно проложить магистральный кабель между всеми парами городов, но это будет неоправданно дорого. Меньшую стоимость будет иметь решение, при котором города будут соединены связями, которые содержатся в наименьшем остовном дереве. На рис. 12.5 показаны шесть городов, каждые два из которых соединены магистральным кабелем. Жирными линиями нарисовано наименьшее остовное дерево.

Заметьте, что сеть может иметь несколько наименьших остовных деревьев. На рис. 12.6 показаны два изображения сети с двумя различными наименьшими остовными деревьями, которые нарисованы жирными линиями. Полная цена обоих деревьев равна 32.

@Рис. 12.5. Магистральные телефонные кабели, связывающие шесть городов

========320

@Рис. 12.6. Два различных наименьших остовных дерева для одной сети

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

Этот алгоритм похож на эвристику восхождения на холм, описанную в 8 главе. На каждом шаге оба алгоритма изменяют решение, пытаясь его максимально улучшить. Алгоритм остовного дерева на каждом шаге выбирает связь с наименьшей ценой, которая добавляет новый узел в дерево. В отличие от эвристики восхождения на холм, которая не всегда находит наилучшее решение, этот алгоритм гарантированно находит наименьшее остовное дерево.

Подобные алгоритмы, которые находят глобальный оптимум, при помощи серии локально оптимальных приближений называются поглощающими алгоритмами[RV20] (greedy algorithms). Можно представлять себе поглощающие алгоритмы как алгоритмы типа восхождения на холм, не являющиеся при этом эвристиками — они гарантированно находят наилучшее возможное решение.

Алгоритм наименьшего остовного дерева использует коллекцию для хранения списка связей, которые могут быть добавлены к остовному дереву. Вначале алгоритм помещает в этот список связи корневого узла. Затем проводится поиск связи с наименьшей ценой в этом списке. Чтобы максимально ускорить поиск, программа может использовать приоритетную очередь типа описанной в 9 главе. Или наоборот, чтобы упростить реализацию, программа может использовать для хранения списка возможных связей коллекцию.

Если узел на другом конце связи еще не находится в остовном дереве, то программа добавляет его и соответствующую связь в дерево. Затем она добавляет связи, выходящие из нового узла, в список возможных узлов.

Алгоритм использует флаг Used в классе link, чтобы определить, попадала ли эта связь ранее в список возможных связей. Если да, то она не заносится в этот список снова.

Может оказаться, что список возможных связей опустеет до того, как все узлы будут добавлены в остовное дерево. В этом случае сеть является несвязной, и не существует путь, который связывает корневой узел со всеми остальными узлами сети.

=========321

Private Sub FindSpanningTree(root As SpanNode)

Dim candidates As New Collection

Dim to_node As SpanNode

Dim link As SpanLink

Dim i As Integer

Dim best_i As Integer

Dim best_cost As Integer

Dim best_to_node As SpanNode

    If root Is Nothing Then Exit Sub

   

    ' Сбросить флаг Marked для всех узлов и флаги

    ' Used и InSpanningTree для всех связей.

    ResetSpanningTree

    ' Начать с корня остовного дерева.

    root.Marked = True

    Set best_to_node = root

    Do

        ' Добавить связи последнего узла в список

        ' возможных связей.

        For Each link In best_to_node.Links

           If Not link.Used Then

               candidates.Add link

               link.Used = True

           End If

        Next link

        ' Найти самую короткую связь в списке возможных

        ' связей, которая ведет к узлу, которого еще нет

        ' в дереве.

        best_i = 0

        best_cost = INFINITY

        i = 1

        Do While i <= candidates.Count

           Set link = candidates(i)

           If link.Node1.Marked Then

               Set to_node = link.Node2

           Else

               Set to_node = link.Node1

           End If

           If to_node.Marked Then

               ' Связь соединяет два узла, которые

               ' оба находятся в дереве.

               ' Удалить ее из списка возможных связей.

               candidates.Remove i

           Else

               If link.Cost < best_cost Then

                   best_i = i

                   best_cost = link.Cost

                   Set best_to_node = to_node

               End If

               i = i + 1

           End If

        Loop

       

        ' Если больше не осталось связей, которые можно

        ' было бы добавить, то мы сделали все, что могли.

        If best_i < 1 Then Exit Do

        ' Добавить наилучшую связь и узел на ее конце в дерево.

        Set link = candidates(best_i)

        link.InSpanningTree = True

        candidates.Remove best_i

       

        best_to_node.Marked = True

    Loop

    GotSpanningTree = True

   

    ' Перерисовать сеть.

    DrawNetwork

End Sub

Этот алгоритм проверяет каждую связь не более одного раза. При проверке каждой связи, она добавляется в список возможных связей, а затем удаляется из него. Если этот список находится в приоритетной очереди на основе пирамид, то для вставки или удаления элемента из очереди потребуется время порядка O(log(N)), где — число связей в сети. В этом случае полное время выполнения алгоритма будет порядка O(N * log(N)).

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82


Новости


Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

                   

Новости

© 2010.