скачать рефераты
  RSS    

Меню

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

скачать рефераты

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

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

В табл. 11.5 приведены преимущества и недостатки различных методов хеширования.

======310

@Таблица 11.5. Преимущества и недостатки различных методов хеширования

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

=======311

Глава 12. Сетевые алгоритмы

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

Определения

Как и в определении деревьев, сетью (network) или графом (graph) называется набор узлов (nodes), соединенных ребрами (edges) или связями (links). Для графа, в отличие от дерева, не определено понятие родительского или дочернего узла.

С ребрами сети может быть связано соответствующее направление, тогда в этом случае сеть называется ориентированной сетью (directed network). Для каждой связи можно также определить ее цену (cost). Для сети дорог, например, цена может быть равна времени, которое займет проезд по отрезку дороги, представленному ребром сети. В телефонной сети цена может быть равна коэффициенту электрических потерь в кабеле, представленном связью. На рис. 12.1 показана небольшая ориентированная сеть, в которой числа рядом с ребрами соответствуют цене ребра.

Путем (path) между узлами A и B называется последовательность ребер, которая связывает два этих узла между собой. Если между любыми двумя узлами сети есть не больше одного ребра, то путь можно однозначно описать, перечислив входящие в него узлы. Так как такое описание проще представить наглядно, то пути по возможности описываются таким образом. На рис. 12.1 путь, проходящий через узлы B, E, F, G,E и D, соединяет узлы B и D.

Циклом (cycle) называется путь который связывает узел с ним самим. Путь E, F, G, E на рис. 12.1 является циклом. Путь называется простым (simple), если он не содержит циклов. Путь B, E, F, G, E, D не является простым, так как он содержит цикл E, F, G, E.

Если существует какой‑либо путь между двумя узлами, то должен существовать и простой путь между ними. Этот путь можно найти, если удалить все циклы из исходного пути. Например, если заменить цикл E, F, G, E в пути B, E, F, G, E, D на узел E, то получится простой путь B, E, D, связывающий узлы B и D.

=======313

@Рис. 12.1. Ориентированная сеть с ценой ребер

Сеть называется связной (connected), если между любыми двумя узлами существует хотя бы один путь. В ориентированной сети не всегда очевидно, является ли сеть связной. На рис. 12.2 сеть слева является связной. Сеть справа не является связной, так как не существует пути из узла E в узел C.

Представления сети

В 6 главе было описано несколько представлений деревьев. Большинство из них применимо также и для работы с сетями. Например, представления полными узлами, списком потомков (списком соседей для сетей) или нумерацией связей также могут использоваться для хранения сетей. За описанием этих представлений обратитесь к 6 главе.

@Рис. 12.2. Связная (слева) и несвязная (справа) сети

======314

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

Кроме этого, некоторые варианты представления ребер могут упростить работу с определенными типами сетей. Эти представления используют один класс для узлов и другой — для представления связей. Применение класса для связей облегчает работу со свойствами связей, такими, как цена связи.

Например, ориентированная сеть с ценой связей может использовать следующее определения для класса узла:

Public Id As Integer              ' Номер узла.

Public Links As Collection        ' Связи, ведущие к соседним узлам.

Можно использовать следующее определение класса связей:

Public ToNode As NetworkNode      ' Узел на другом конце связи.

Public Cost As Integer     ' Цена связи.

Используя эти определения, программа может найти связь с наименьшей ценой, используя следующий код:

Dim link As NetworkLink

Dim best_link As NetworkLink

Dim best_cost As Integer

    best_cost = 32767

    For Each link In node.Links

        If link.cost < best_cost Then

           Set best_link = link

           best_cost = link.cost

        End If

    Next link

Классы node и link часто расширяются для удобства работы с конкретными алгоритмами. Например, к классу node часто добавляется флаг Marked. Если программа обращается к узлу, то она устанавливает значение поля Marked равным true, чтобы знать, что узел уже был проверен.

Программа, управляющая неориентированной сетью, может использовать немного другое представление. Класс node остается тем же, что и раньше, но класс link включает ссылку на оба узла на концах связи.

Public Node1 As NetwokNode        ' Один из узлов на конце связи.

Public Node2 As NetwokNode        ' Другой узел.

Public Cost As Integer     ' Цена связи.

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

=======315

Используя это представление, программа NetEdit позволяет оперировать неориентированными сетями с ценой связей. Меню File (Файл) позволяет загружать и сохранять сети в файлах. Команды в меню Edit (Правка) позволяют вам вставлять и удалять узлы и связи. На рис. 12.3 показано окно программы NetEdit.

Директория OldSrc\Ch12 содержит программы, которые используют представление нумерацией связей. Эти программы немного сложнее понять, но они обычно работают быстрее. Они не описаны в тексте, но использованные в них методы похожи на те, которые применялись в программах, написанных для 4 версии Visual Basic. Например, обе программы Src\Ch12\Paths и OldSrc\Ch12\Paths находят кратчайший маршрут, используя описанный ниже алгоритм установки меток. Основное отличие между ними заключается в том, что первая программа использует коллекции и классы, а вторая — псевдоуказатели и представление нумерацией связей.

Оперирование узлами и связями

Корень дерева — это единственный узел, не имеющий родителя. Можно найти любой узел в сети, начав от корня и следуя по указателям на дочерние узлы. Таким образом, узел представляет основание дерева. Если ввести переменную, которая будет содержать указатель на корневой узел, то впоследствии можно будет получить доступ ко всем узлам в дереве.

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

Поэтому программы, работающие с сетями, обычно содержат полный список всех узлов в сети. Программа также может хранить полный список всех связей. При помощи этих списков можно легко выполнить какие‑либо действия над всеми узлами или связями в сети. Например, если программа хранит указатели на узлы и связи в коллекциях Nodes и Links, она может вывести сеть на экран при помощи следующего метода:

@Рис. 12.3. Программа NetEdit

=======316

Dim node As NetworkNode

dim link As NetworkLink

    For Each link in links

        ' Нарисовать связь.

           :

    Next link

    For Each node in nodes

        ' Нарисовать узел.

           :

    Next node

Программа NetEdit использует коллекции Nodes и Links для вывода сетей на экран.

Обходы сети

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

Алгоритм для выполнения прямого обхода двоичного дерева, описанный в 6 главе, формулируется так:

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

       Выполнить рекурсивный прямой обход левого поддерева.

       Выполнить рекурсивный прямой обход правого поддерева.

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

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

Чтобы избежать этого, алгоритм должен помечать узел после обращения к нему, при этом при поиске в соседних узлах, обращение происходит только к узлам, которые еще не были помечены. После того, как алгоритм завершит работу, все узлы в сети будут помечены (если сеть является связной). Алгоритм прямого обхода сети формулируется так:

       Пометить узел.

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

       Выполнить рекурсивный обход не помеченных соседних узлов.

========317

В Visual Basic можно добавить флаг Marked к классу NetworkNode.

Public Id As Long

Public Marked As Boolean

Public Links As Collection

Класс NetworkNode может включать открытую процедуру для обхода сети, начиная с этого узла. Процедура узла PreorderPrint обращается ко всем непомеченным узлам, которые доступны из данного узла. Если сеть является связной, то при таком обходе произойдет обращение ко всем узлам сети.

Public Sub PreorderPrint()

Dim link As NoworkLink

Dim node As NetworkNode

    ' Пометить узел.

    Marked = True

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

    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). Можно представлять себе поглощающие алгоритмы как алгоритмы типа восхождения на холм, не являющиеся при этом эвристиками — они гарантированно находят наилучшее возможное решение.

Страницы: 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


Новости

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

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

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

© 2010.