Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
63
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 57 Графомания

Я чуть не забыл о придворном программисте Нике! В 49-й главе он решил задачу о минимальной сумме пошлин. Тогда же купцы уговорили его взяться за программу для поиска кратчайшего маршрута между двумя странами. Купцы страдали от пошлин и хотели сократить свои расходы на границах. Ник принял заказ и впал в размышления.

На рис. 130 показан вид из космоса на континент, где проживал Ник. Тамошние страны именовались, как вы помните, латинскими буквами.

H

B

C

I

G A

D

F

E

Рис. 130 – Карта континента

Программа, что создал Ник в 38-й главе, превратила эту карту в следующий файл.

450

Глава 57

Графомания

A B D F I

B A C I H

C B D

D A C E

E D F

F A E G

G H I F

H G I B

I A B G H

В каждой строке файла представлены соседи одной страны: первый символ — это название самой страны, а последующие — её соседи, перечисленные в произвольном порядке. В любом порядке могут следовать и сами строки, — от этого карта не изменится, согласны? Итак, этот файл содержал данные для поиска кратчайшего маршрута.

Данные были, только решение куда-то ускользало. Вот берег озера, где спрятался Ник. Его рука в который раз царапает на мокром песке одну и ту же картинку (рис. 131).

H

B

G I C

A

F

D

E

Рис. 131 – Картинка на мокром песке

Здесь вместо разделяющих царства границ, Ник нацарапал соединяющие их дороги. «Вот по этим дорогам поедут купцы, — размышлял он, — но как именно?». Озарение явилось внезапно. «Постой-ка, мне знакома эта картинка! Неужто граф? Я что-то читал о них, надо бы вспомнить!». Оставим ненадолго озаренного Ника, и выясним, что это за штука такая — граф?

451

Глава 57

Графомания

Видимое представление графа

Слово «граф» намекает на рисование, графику. Но программисты и математики признают графом не любую картинку. Граф для них — это сеть связанных между собой объектов. Объекты называют вершинами или узлами графа, а связи между ними — ребрами или дугами. В англоязычной литературе

используют термины Node — узел, и Link — связь.

Вот знакомая картинка — схема московского метро (Рис. 132), это пример графа. Здесь станции являются узлами графа, а пути между ними — ребрами. Соседние узлы графа называют смежными. Кстати, нырнувший в метро пассажир решает ту же задачу, что и Ник: ищет кратчайший путь между двумя станциями.

Рис. 132 – Схема московского метрополитена – это граф

А вот ещё примеры графов: карта автомобильных дорог, дерево родственных связей, электрическая схема. Вы можете придумать свои примеры. Или взять нацарапанный Ником рисунок, где узлами являются страны, а ребрами — дороги, их соединяющие.

Мы рассмотрели внешнее, видимое представлении графа, теперь обратимся к его внутреннему представлению в памяти компьютера.

452

Глава 57

Графомания

Внутреннее представление графа

С внутренним представлением графа вы отчасти знакомы. Не удивляйтесь, ведь односвязный список — это тоже граф. Элементы списка — это узлы графа, а связи между элементами — это ребра. И хотя связь между узлами списка однонаправленная, такие графы тоже имеют право на жизнь. Разве нет дорог с односторонним движением?

Голова списка

Ребро Узел

A B C D

Рис. 133 – Односвязный список – это разновидность графа

Годится ли такой список для представления графа, нацарапанного Ником? Рисунок на песке очевидно сложнее списка, — в нём много связей между узлами. К тому же связи на схеме Ника двунаправленные, ведь по дорогам можно ехать в обе стороны. Для представления такого графа требуется что-то похитрее списка. Но в этой замысловатой конструкции найдется место и односвязным спискам.

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

Теперь о связях. Очевидно, что их представим указателями. Но сколько их потребуется? Ведь из разных узлов исходит разное количество связей (рис. 131). Я предлагаю поместить в каждом узле список его связей с соседями. Неслабый получается узелок — с собственным списком внутри! Устройство этого списка связей мы обсудим чуть позже.

Но и это не всё. Поскольку узлы графа погружаются в кучу, нужно средство для доступа к ним. Вы знаете его — это односвязный список. Значит, внутри каждого узла нужен указатель mNext для включения узла в этот вспомогательный список. В итоге наших размышлений проясняется внутреннее представление графа, показанное на рис. 134.

453

 

 

Глава 57

 

 

 

Графомания

 

 

Вспомогательный список

 

Голова

 

узлов

 

 

 

 

 

Список ребер

 

Элемент связи

H

 

 

 

mLink

mNode

mNode

mNode

mNext

mNext

mNext

NIL

 

Узел графа

 

 

G

 

 

 

mLink

 

 

 

mNext

 

 

 

I

 

 

Ребро графа

 

 

 

mLink

 

 

 

mNext

 

 

 

B

 

 

 

mLink

 

 

 

mNext

 

 

 

 

Рис. 134 – Организация связей графа на примере узла H

Слева видны тонкие стрелки, ведущие сверху вниз — это вспомогательный список, на который нанизаны узлы графа. Порядок следования узлов в этом списке не важен, важно лишь то, что двигаясь от головы списка по ссылкам mNext, можно достать любой узел. Этот список не определяет зримых связей между узлами.

454

Глава 57

Графомания

Видимые нам ребра графа формируются списками, что вставлены внутрь каждого узла. Головы этих списков — это поля mLink. Чтобы не загромождать схему, я показал лишь список для узла H. Элементы списка связей вытянулись на схеме слева направо, они сцеплены полями mNext, — не путайте их с полями mNext в узлах графа. Полезной нагрузкой элементов списка связей будут указатели mNode, ссылающиеся на соседние узлы. Именно эти ссылки, показанные на схеме жирными стрелками, определяют видимую форму графа, то есть его ребра. На рис. 135 показана часть графа, соответствующая схеме рис. 134.

H

B

G I

Рис. 135 – Часть графа, соответствующая схеме рис. 134

Здесь показаны лишь ребра, идущие от узла H, но подобные списки содержатся и в других узлах. Например, в списке связей узла G есть ссылка на узел H, поскольку узлы взаимно связаны. Так парами указателей создаётся двусторонняя связь узлов G H (рис. 136).

H H

G G

Рис. 136 – Ребро графа (слева) и внутреннее его представление (справа)

Прежде, чем выразить эту мудреную структуру на Паскале, повторю основные идеи.

Узлы графа представлены записями.

Каждая запись узла содержит: 1) полезные поля, 2) голову списка ребер и 3) указатель на следующий узел во вспомогательном списке.

Полезной нагрузкой в списке ребер являются указатели на смежные узлы графа.

455

Соседние файлы в папке delphi