Загрузил Fergitys5

РПЗ

Реклама
Введение
Целью этой КР (курсовой работы) является получение навыков по следующим
направлениям:

разработка приложений и их реализация средствами среды
программирования Delphi;

использование концепции ООП (объектно-ориентированного
программирования) и применение средств языка Object Pascal для ее
реализации;

работа с динамической памятью и динамическими структурами данных;
В результате выполнения работы созданы: класс, обеспечивающий работу с такой
структурой данных как граф, и класс, позволяющий создавать и обрабатывать линейные
двусвязные списки.
Также было создано приложение Metro, в соответствии с содержательной задачей
КР. Это приложение демонстрирует использование разработанных классов, их методов и
демонстрирует возможности разработки графических приложений с диалоговым
интерфейсом в среде Delphi.
2
1. Теоретическая часть
1.1 Особенности ООП
1.1.1 Основные концепции ООП
Язык Object Pascal является объектно-ориентированным расширением языка Pascal
и реализует концепцию ООП. Это означает, что функциональность приложения
определяется набором связанных между собой задач, каждая из которых становится
самостоятельным объектом. Объект имеет свои свойства (т.е. характеристики, или
атрибуты), методы, определяющие его поведение, и события, на которые он реагирует.
Одним из наиболее важных понятий ООП является класс. Класс представляет собой
дальнейшее развитие концепции типа и объединяет в себе задание не только структуры и
размера переменных, но и выполняемых над ними операций. Объекты в программе всегда
являются экземплярами того или иного класса.
Базой ООП являются:

инкапсуляция;

наследование;

полиморфизм;
Инкапсуляция представляет собой объединение данных и обрабатывающих их
методов внутри класса. Это означает, что в классе объединяются и помещаются внутрь
поля, свойства и методы. При этом класс получает определенную функциональность.
Наследование – это процесс порождения новых объектов-потомков от
существующих объектов-родителей, при этом потомок берет от родителя все его поля,
свойства и методы. В дальнейшем наследуемые поля, свойства и методы можно
использовать в неизменном виде или переопределять.
Просто наследование большого смысла не имеет, поэтому в объект-потомок
добавляются новые элементы, определяющие его особенность и функциональность.
Удалить какие-либо элементы родителя в потомке нельзя. В свою очередь от нового
объекта можно породить следующий объект, в результате образуется дерево объектов
(называемое также иерархией классов).
Сущность полиморфизма заключается в том, что методы различных классов могут
иметь одинаковые имена, но различное содержание. Это достигается переопределением
родительского метода в классе-потомке. В результате родитель и потомок ведут себя поразному. При этом обращение к одноименным методам различных объектов выполняется
аналогично.
1.1.2 Классы и объекты
В языке Object Pascal классы – это специальные типы данных, используемые для
описания объектов. Соответственно объект, имеющий тип какого-либо класса, является
экземпляром этого класса и переменной этого типа.
Класс представляет собой особый тип записи, имеющий в своем составе такие
элементы, как поля, свойства и методы. Поля класса аналогичны полям записи и служат
3
для хранения информации об объекте. Методами называются процедуры и функции,
предназначенные для обработки полей. Свойства занимают промежуточное положение
между полями и методами. С одной стороны, свойства можно использовать как поля, с
другой, внутри класса доступ к значениям свойств выполняется методами класса.
Описание класса имеет следующую структуру:
Type <Имя класса> = class (<Имя класса-родителя>)
private
<Частные описания>;
protected
<Защищенные описания>;
public
<Общедоступные описания>;
published
<Опубликованные описания>;
end;
Если в качестве родительского используется класс TObject, который является
базовым классом для всех классов, то его имя после слова class можно не указывать.
Для различных элементов класса можно устанавливать разные права доступа
(видимости), для чего в описании класса используются отдельные разделы, обозначенные
специальными спецификаторами видимости.
Разделы private и protected содержат защищенные описания, которые
доступны внутри модуля, в котором они находятся. Описания из раздела protected,
кроме того, доступны для порожденных классов за пределами названного модуля.
Раздел public содержит общедоступные описания, которые видимы в любом
месте программы, где доступен сам класс.
Раздел published содержит опубликованные описания, которые в дополнение к
общедоступным описаниям порождают динамическую информацию о типе (Run-Time
Type Information, RTTI). По этой информации при выполнении приложения производится
проверка на принадлежность элементов объекта тому или иному классу. Если
спецификатор published не указан, то он подразумевается по умолчанию, поэтому
описания, расположенные за строкой с указанием имени класса, считаются
опубликованными.
Объекты как экземпляры класса объявляются в программе в разделе var как
обычные переменные.
1.1.3 Поля
Поле класса представляет собой данные, содержащиеся в классе. Поле описывается
как обычная переменная и может принадлежать к любому типу. Согласно принятому
соглашению, имена полей должны начинаться с буквы f (от англ. Field – поле).
При создании новых классов класс-потомок наследует все поля родителя, при этом
удаление или переопределение этих полей невозможно, но допускается добавление новых.
Таким образом, чем дальше по иерархии какой-нибудь класс находится от родительского
класса, тем больше полей он имеет.
4
Изменение значений полей обычно выполняется с помощью методов и свойств
объекта.
1.1.4 Свойства
Свойства реализуют механизм доступа к полям. Каждому свойству соответствует
поле, содержащее значение свойства, и два метода, обеспечивающих доступ к этому
полю. Описание свойства начинается со слова property, при этом типы свойства и
соответствующего поля должны совпадать. Ключевые слова read и write являются
зарезервированными внутри объявления свойства и служат для указания методов класса, с
помощью которых выполняется чтение значения поля или запись нового значения в него.
Пример описания свойств:
type TnewClass = class
private
Fcode: integer;
published
property Code: integer read Fcode write Fcode;
end;
Для доступа к полю FCode, которое описано в защищенном разделе и недоступно
другим классам, используется свойство Code.
1.1.5 Методы
Метод представляет собой подпрограмму, являющуюся элементом класса.
Описание метода похоже на описание обычной подпрограммы модуля. Заголовок метода
располагается в описании класса, а сам код метода находится в разделе реализации. Имя
метода в разделе реализации является составным и включает в себя тип класса.
Метод, объявленный в классе может вызываться различными способами, что
зависит от вида этого метода. Вид метода определяется модификатором, который
указывается в описании класса после заголовка метода и отделяется от заголовка точкой с
запятой. Вот некоторые из модификаторов:
 virtual – виртуальный метод;
 dynamic – динамический метод;
 override – переопределяемый метод;
 message – обработка сообщения;
 abstract – абстрактный метод;
По умолчанию все методы, объявленные в классе, являются статическими и
вызываются как обычные подпрограммы.
Методы, которые предназначены для создания или удаления объектов, называются
конструкторами и деструкторами, соответственно. Описания данных методов
отличаются от описания обычных процедур только тем, что в их заголовках стоят
ключевые слова constructor и destructor.
5
1.2 Динамические информационные структуры
1.2.1 Динамическая память
Все переменные, объявленные в программе, размещаются в одной непрерывной
области оперативной памяти, которая называется сегментом данных. Длина сегмента
данных определяется архитектурой микропроцессора 80х86 и составляет 65536 байт, что
может вызвать известные затруднения при обработке больших массивов данных.
Выходом из положения может служить использование так называемой динамической
памяти.
Динамическая память – это оперативная память ПК (персонального компьютера),
предоставляемая программе при ее работе, за вычетом сегмента данных, стека и
собственно тела программы. Размер динамической памяти можно варьировать в широких
пределах.
Динамическое размещение данных означает использование динамической памяти
непосредственно при работе программы. В отличие от этого, статическое размещение
осуществляется компилятором в процессе компиляции программы. При динамическом
размещении заранее не известны ни тип, ни количество размещаемых данных, к ним
нельзя обратится по именам, как к статическим переменным.
1.2.2 Указатели
Указатель представляет собой переменную, значением которой является адрес
начала размещения некоторых данных в динамической памяти. Иными словами, указатель
содержит ссылку на соответствующий объект. Указатели могут ссылаться на данные
любого типа. Переменные типа указателя являются динамическими – значения их
определяются во время выполнения программы.
Различают типизированные и нетипизированные указатели. Типизированный
указатель может ссылаться на данные определенного типа, который указывается при
объявлении указателя или описании его типа.
Нетипизированный указатель имеет тип Pointer и может ссылаться на данные
любого типа.
Пример объявления указателей:
var
PInt: ^integer;
Ptr: pointer;
В этом примере PInt – типизированный указатель, он имеет тип integer, а Ptr –
нетипизированный указатель.
С помощью указателя можно получить доступ к значению адресуемых данных. Для
этого используется операция разыменовывания указателя – справа от имени указателя
приписывается знак ^.
Указателю можно присвоить константу nil, это означает, что данный указатель ни
на что не указывает.
Для определения адреса ссылаемого с помощью указателя объекта используется
операция @, записываемая перед именем этого объекта.
6
Память под любую динамически размещаемую переменную выделяется
процедурой New. Параметром обращения к этой процедуре является типизированный
указатель. В результате обращения указатель приобретает значение, соответствующее
динамическому адресу, начиная с которого можно разместить данные.
Освобождение динамической памяти, связанной с некоторым указателем,
осуществляется с помощью процедуры Dispose. Параметром этой процедуры является
указатель, который ссылается на начало области памяти, которую нужно освободить.
1.2.3 Динамические структуры данных
Все динамические структуры объединяет принцип их построения. Все они
представляют собой совокупность объектов (обычно записей, при этом одним из полей
записи должен быть указатель на следующую запись), связанных ссылками (указателями
того же типа, что и записи) и располагающихся в динамической памяти (также
называемой кучей).
Пример объявления элемента динамической структуры:
type
PNode = ^Node;
Node = record
Key: integer;
Next: ^PNode;
end;
Здесь PNode – указатель на элемент динамической структуры Node, где Key – ключ
элемента, а Next – указатель на следующий элемент.
Существует множество динамических типов данных, например, стек, очередь и
многие другие. Мы рассмотрим динамическую структуру данных, которая называется
линейный список.
1.2.4 Линейный список
В линейном списке каждый элемент связан со следующим и, возможно, с
предыдущим. В первом случае список называется односвязным, во втором – двусвязным.
Если последний элемент связать указателем с первым, получится кольцевой список.
Каждый элемент списка содержит ключ, идентифицирующий этот элемент. В
качестве ключа в процессе работы со списком могут выступать разные части поля данных.
Ключи разных элементов списка могут совпадать.
На рис. 3.1 показан пример списковой структуры и связь элементов в списке:
Рис 1.1 Пример списка.
7
1.3 Некоторые сведения из теории графов
Поскольку содержательная задача КР является графовой задачей, приведем
некоторые сведения из теории графов:
Графом называется пара (V,E) , где V – непустое множество объектов некоторой
природы, называемых вершинами графа, а E – подмножество двухэлементных
подмножеств множества V, называемых ребрами графа. Множество вершин и ребер графа
обозначают V(G) и E(G), соответственно. Пример графа приведен на рис. 3.2.
Рис. 1.2 Неориентированный граф.
Пусть v1, v2, …, vi, vi+1, …, vk – последовательность вершин такая, что каждая пара
вершин vi, vi+1 определяет ребро в графе. Тогда данная последовательность называется
маршрутом. Маршрут называется цепью, если ни одна вершина не встречается в нем
дважды.
Граф называется связным, если каждая пара вершин в графе соединена цепью.
Граф, изображенный на рис. 3.2 является связным.
Орграфом называется пара (V,A), где V – непустое множество объектов некоторой
природы, называемых вершинами орграфа, а. А – подмножество двухэлементных
упорядоченных подмножеств множества V, называемых дугами орграфа. Множества
вершин и дуг орграфа G обозначают V(G) и A(G), соответственно. На рис. 3.3 показан
пример орграфа.
Рис. 1.3 Ориентированный граф.
Взвешенным графом (орграфом) называется граф (орграф) у которого ребра (дуги)
имеют какую-либо числовую характеристику (длину, вес, время и т.п.).
Примечание. Реализованный в КР класс, описывающий графы, работает со
связными взвешенными ориентированными графами.
8
2. Проектная часть
2.1 Постановка задачи и выбор метода решения
Задача КР заключалась в создании класса, оперирующего линейным двусвязным
списком и в его применении при решении графовых задач. Однако для решения такого
рода задач линейный список является не очень удобной структурой, поэтому был
разработан класс, описывающий любые связные графы. Класс, в котором количество
связей при вершине графа и характер связей вершин определяется пользователем.
Класс, работающий с линейным списком, был также разработан, а сам линейный
список используется для хранения кратчайшего пути из одной вершины графа в другую,
хотя для этого подошла бы любая структура, как динамическая, так и статическая,
позволяющая хранить последовательность каких-либо связанных объектов (например,
очередь, стек, массив).
2.2 Определение типа элемента структуры и основных алгоритмов
2.2.1 Описание типа элемента структуры
Класс TGraph описывает динамическую структуру данных – граф, которая
хранится в памяти именно как граф, с конфигурацией, задаваемой пользователем. Такой
подход позволяет гораздо проще реализовывать математические алгоритмы работы с
графами и упрощает представление пользователя о хранение графа в памяти, более того,
при решении некоторых задач (например, о кратчайших расстояниях), такой подход
позволяет не использовать дополнительную память для хранения вспомогательных
динамических структур.
Максимальное количество связей при вершине графа n задается пользователем в
следующей строчке раздела const:
const
n = 4;
Это означает, что любая вершина графа может содержать от 1 до n ребер,
связывающих ее с другими вершинами.
Следующие две строчки определяют типы ключа (названия) вершины и веса ее
ребер:
type
TKey = string[40]; //Тип ключа
TWeight = real;
//Тип весов
Вершины графа определены в виде записей следующим образом:
PNode = ^Node;
Node = record
Key: TKey;
Pointers: array [1..n] of PNode;
Weights: array [1..n] of TWeight;
Marked: boolean;
9
Ancestor: PNode;
TotalWeight: TWeight;
end;
Где Pnode – указатель на Node, Key – ключ вершины, Pointers – массив
указателей, ссылающихся на соседние вершины, или по-другому – это ребра (дуги),
исходящие из вершины Node, Weights – массив весов ребер (дуг), выходящих из
вершины Node. При этом у элемента массива весов и у ребра из массива ребер, чей вес
хранит этот элемент массива весов, совпадают номера.
Следующие три поля используются для реализации алгоритма поиска кратчайшего
пути: Marked – хранит состояние вершины пройдена/непройдена, Ancestor – хранит
указатель на предка, через которого лежит кратчайший путь до корневой вершины,
TotalWeight – хранит общий вес от источника до данной вершины.
С помощью полей Ancestor и TotalWeight, не используя дополнительной
памяти, прямо в графе, строится дерево кратчайших расстояний от заданной вершины до
всех других.
2.2.2 Описание основных алгоритмов
Алгоритм поиска кратчайшего пути, разработанный в КР похож на алгоритм
Дейкстры, но все-таки отличается от него. Вот его описание:
Алгоритм поиска кратчайших расстояний
Пусть каждая вершина может быть в двух состояниях – ПРОЙДЕНА и
НЕПРОЙДЕНА. Пусть f(t) хранит указатель на предка вершины, через которого проходит
кратчайший путь до источника, а s – вершина-источник, от которой нужно построить
дерево кратчайших расстояний. Пусть также l(x,t) – вес ребра х-t, wt – общий вес пути от s
до t
проц ДЕРЕВО-РАССТОЯНИЙ(t, s)
начало
ПОМЕТИТЬ-ПРОЙДЕНА(t);
Для каждого соседа x вершины t цикл
если НЕПОМЕЧЕНА(х) и х<>s то
если wx =0 или wx >wt+l(x,t) то
Положить wx =wt+l(x,t) и
положить f(x)=t;
ДЕРЕВО-РАССТОЯНИЙ(х, s);
все
все
все
Для каждого соседа х вершины t цикл
если НЕПОМЕЧЕНА(х) и х<>f(t) то
ПОМЕТИТЬ-НЕПРОЙДЕНА(x);
все
все
конец
Как видно алгоритм рекурсивный.
10
Другой алгоритм, использующийся при поиске элементов в графе и при обходе
графа для разных целей, называется рекурсивным алгоритмом обхода графа в глубину.
Его описание приведено ниже.
Рекурсивный алгоритм обхода графа в глубину
проц РЕКУРСИВНЫЙ-ОБХОД(p: вершина)
начало
Посетить вершину p;
для всех q из множества вершин, смежных с p цикл
если q еще не посещалась то
РЕКУРСИВНЫЙ-ОБХОД(q);
все
все
конец
2.3 Описание разработанных классов
2.3.1 Описание класса TGraph
Интерфейсная часть класса TGraph выглядит следующим образом:
TGraph = class
public
FRoot: PNode;
procedure
procedure
procedure
function
procedure
protected
procedure
procedure
procedure
procedure
end;
Add(Key: TKey); overload;
Add(Key1,Key2: TKey; x1,x2: byte;
w: TWeight; var Code: byte); overload;
Tie(Key1,Key2: TKey; x1,x2: byte;
w: TWeight);
Search(Key: TKey; var p: PNode): boolean;
Route(Key1,Key2: TKey; List1: TList;var w:
TWeight);
Unmark(var Root: PNode);
Find(var Root: PNode; Key: TKey; var p: PNode;
var b: boolean);
PassAndWeight(var p: PNode);
UnWeight(var p: PNode);
Поле FRoot хранит указатель на корень графа. Корнем автоматически становится
первый элемент графа. Корневой указатель нужен для того, чтобы всегда можно было
войти в граф, а так как он связный, то совершенно неважно, какая именно вершина будет
корнем.
В защищенном разделе, начинающимся словом protected, описаны четыре
рекурсивные процедуры: Unmark, Find, PassAndWeight и UnWeight, реализующие
алгоритмы, описанные выше. Чтобы скрыть от пользователя механизм реализации, и для
корректной работы этих алгоритмов, описаны подпрограммы Search и Route,
использующие скрытые процедуры и доступные пользователю.
11
Далее следует описание методов класса TGraph, с указанием параметров и того,
что делает метод.

Procedure
Add(Key: TKey); overload;
Описание:
Добавляет новый элемент, если граф не содержал до этого ни одной
вершины.
Параметры:
Key – ключ нового элемента

Procedure Add(Key1,Key2: TKey; x1,x2: byte;
w: TWeight; var Code: byte); overload;
Описание:
Добавляет новый элемент, если граф уже содержит вершины и связывает
его с любой из существующих вершин дугой.
Параметры:
Key1 – ключ нового элемента
Key2 – ключ элемента, с которым нужно связать новый
x1 – номер ребра нового элемента, которое нужно связать с уже
существующим элементом
x2 – номер ребра элемента, которое нужно связать с новым элементом
w – вес этой связи (дуги)
Code – параметр, хранящий коды ошибок при добавление нового элемента
Коды ошибок:
Code=0: добавление прошло успешно
Code=1: неправильный ввод номеров ребер или веса
Code=2: Элемент с ключом Key2 не найден
Code=3: Ребра уже связаны
Примечание: В описанных выше двух процедурах Add используется механизм
перегрузки имен, на что указывает модификатор overload, стоящий после заголовков этих
процедур. В зависимости от количества фактических параметров вызываемой
подпрограммы, вызывается одна из них, с тем же количеством параметров.

Procedure
Tie(Key1,Key2: TKey; x1,x2: byte;
w: TWeight);
Описание:
Связывает две уже существующие вершины дугой.
Параметры:
Key1 – ключ первого элемента
Key2 – ключ второго элемента
x1 – номер ребра первого элемента
x2 – номер ребра второго элемента
w – вес этой связи (дуги)
12

Function
Search(Key: TKey; var p: PNode): boolean;
Описание:
Функция поиска элемента по ключу. Возвращает true, если элемент найден,
false – в обратном случае.
Параметры:
Key – ключ элемента, который нужно найти
p – указатель, который в случае, если искомый элемент найден, хранит
ссылку на него

Procedure
TWeight);
Route(Key1,Key2: TKey; List1: TList; var w:
Описание:
Ищет кратчайшее расстояние между двумя вершинами и сохраняет путь в
линейном списке List1.
Параметры:
Key1 – ключ вершины отправления
Key2 – ключ вершины назначения
List1 – список, куда сохраняется кратчайший путь
w – переменная, в которую сохраняется полный вес кратчайшего пути
Как уже говорилось, в разделе protected размещены служебные функции,
реализующие рекурсивные алгоритмы поиска и нахождения кратчайшего пути:

Procedure
Unmark(var Root: PNode);
Описание:
Помечает все вершины НЕПРОЙДЕНА.
Параметры:
Root – указатель на корень графа

Procedure
Find(var Root: PNode; Key: TKey; var p: PNode;
var b: boolean);
Описание:
Организует рекурсивный поиск в графе, используя рекурсивный алгоритм
обхода графа (см. разд. 2.2.2).
Параметры:
Root – указатель на вершину графа
Key – ключ элемента
p – указатель, ссылающийся на найденный элемент
b – флаг выхода из рекурсии
13

Procedure
PassAndWeight(var p: PNode);
Описание:
Создает в графе, без использования дополнительной памяти, остовное
дерево кратчайших расстояний из точки p до всех остальных вершин,
используя алгоритм поиска кратчайших расстояний (см. разд. 2.2.2).
Параметры:
p – указатель на источник

Procedure
UnWeight(var p: PNode);
Описание:
Устанавливает общие веса вершин в "0".
Параметры:
p – любая вершина
2.3.2 Описание класса TList
Описание типа элемента линейного списка показано ниже:
type
TKey = string[40];
PEl = ^El;
El = record
key: TKey;
prev,
next: PEl;
end;
Здесь TKey – тип ключа, key – ключ элемента списка, prev – указатель на
предыдущий элемент, а next – указатель на следующий элемент.
Примечание: Тип ключа элемента линейного списка должен совпадать с типом
ключа элемента графа.
Интерфейсная часть класса TList:
TList = class
Root: PEl;
Tale: PEl;
procedure
function
procedure
procedure
procedure
end;
AddNode(key: TKey);
Find(key: TKey; var p: PEl): boolean;
InsertAfter(key: TKey; var p: PEl);
InsertBefore(key: TKey; var p: PEl);
DelNode(key: TKey);
Поле Root хранит указатель на начало списка, а поле Tale – на его конец.
14
Описание методов класса, с указанием параметров и назначением изложено ниже:

Procedure
AddNode(key: TKey);
Описание:
Добавляет новый элемент в конец списка.
Параметры:
key – ключ нового элемента

Function
Find(key: TKey; var p: PEl): boolean;
Описание:
Функция поиска элемента по ключу. Возвращает true, если элемент найден
и false в противном случае.
Параметры:
key – ключ нового элемента
p – указатель, в который сохраняется ссылка на найденный элемент

Procedure
InsertAfter(key: TKey; var p: PEl);
Описание:
Вставляет элемент, с заданным ключом после заданного элемента.
Параметры:
key – ключ вставляемого элемента
p – указатель на элемент, после которого нужно вставить данный

Procedure
InsertBefore(key: TKey; var p: PEl);
Описание:
Вставляет элемент, с заданным ключом перед заданным элементом.
Параметры:
key – ключ вставляемого элемента
p – указатель на элемент, после которого нужно вставить данный

Procedure
DelNode(key: TKey);
Описание:
Удаляет элемент с заданным ключом.
Параметры:
key – ключ элемента, который нужно удалить из списка
15
2.4 Описание структуры интерфейса пользователя
Главное окно программы, выглядит так, как показано на рис. 2.1. На нем
изображена схема с тремя линиями московского метрополитена: Сокольнической,
Замоскворецкой и Кольцевой.
Для того чтобы программа вычислила и показала кратчайшее расстояние,
необходимо выбрать любые две станции. Для выбора нужно навести курсор мыши на
кружок рядом с названием станции и нажать любую кнопку мыши. Кружок станет белым.
Далее тем же способом необходимо выбрать вторую станцию.
После того как две станции выбраны, программа найдет кратчайший путь, показав
станции, входящие в этот путь, белыми кружками, а над кнопками появится надпись, вида
"Длительность пути: #### мин.". Где #### количество минут, занимающих данный путь.
Рис. 2.1. Главное окно программы.
В окне программы расположены две кнопки – "Выход" и "Помощь". При нажатии
на кнопку "Выход", происходит закрытие программы. При нажатии на кнопку "Помощь",
появляется окно помощи с описанием того, как работать с программой.
Примечание: Окно помощи является модальным, т.е. пока оно открыто, к основной
программе обратится нельзя.
16
3. Экспериментальная часть
3.1 Содержательная задача и ее решение
Задача:
Дана схема метро, состоящая из двух пересекающихся радиальных линий и
кольцевой линии. Найти кратчайший путь между двумя любыми станциями.
Для решения этой задачи используется класс TGraph для внутреннего
представления схемы метро в памяти в виде графа. Используются также методы этого
класса для нахождения кратчайшего расстояния между любыми двумя станциями.
Для этого связываются одинаковыми именами станции метро и вершины графа,
размещенного в памяти, и, с помощью процедуры Route, находится кратчайшее
расстояние между станциями, и отражается обратно на схему.
Класс TList и его методы используются для создания линейного списка, который
хранит кратчайший путь.
3.2 Тестирование программы Metro
Ниже приведен протокол тестирования, в котором описаны результаты 5 тестов
программы Metro. Для удобства тестирования, длительности между всеми станциями
одинаковы и составляют 3 минуты.
Результаты оформлены в виде рисунков главного окна программы с найденным
путем и длительностью.
Тестировались разные маршруты, в ходе чего проверялась длительность пути. Все
тесты дали положительный результат. На основании этого программа считается
реализованной и готовой для дальнейшей эксплуатации.
17
Протокол тестирования
Тест №1.
Исходные данные: Юго-Западная – Красногвардейская (17 перегонов).
Результат:
18
Тест №2.
Исходные данные: Октябрьская – Проспект мира (6 перегонов).
Результат:
19
Тест №3.
Исходные данные: Сокол – Таганская (8 перегонов).
Результат:
20
Тест №4.
Исходные данные: Новокузнецкая – Комсомольская (4 перегона).
Результат:
21
Тест №5.
Исходные данные: Речной вокзал – Красногвардейская (19 перегонов).
Результат:
22
Инструкция программисту
Разработчику программ, использующему класс TGraph важно следить за связями в
графе, организованном в памяти, поскольку подход, при котором программист сам
определяет характер связей в графе, не позволяет создать общий механизм контроля над
ошибками, и защиту от потерянных в памяти вершин.
Именно поэтому в КР не реализован класс, обеспечивающий контроль над
ошибками. Однако все подпрограммы защищены от неправильно введенных фактических
параметров, и в случае ошибки не выполняется тело подпрограммы.
Количество вершин в графе и максимальное количество связей при вершине
ограничено размером стека оперативной памяти ПК. Так как именно стек реализует
рекурсивный вызов подпрограмм.
Аппаратные средства реализации
Основная программа и модули, содержащие описание разработанных классов
были написаны и протестированы в среде программирования Borland Delphi 7.0 под
управлением операционной системы Microsoft Windows XP Professional Edition.
ПК на котором выполнялась КР имеет следующие системные характеристики:
процессор Intel Pentium III, с тактовой частотой 1266 MHz и размером оперативной
памяти (ОП) 512 Mb.
Программа Metro была также протестирована на машине с процессором Intel
Celeron, с тактовой частотой 533 MHz и размером ОП 128 Mb.
Список литературы
В ходе выполнения КР была использована следующая литература:
Касьянов В. Н., Евстигнеев В. А. "Графы в программировании: обработка,
визуализация и применение". – СПб.: БХВ-Петербург, 2003.
Гофман В. Э., Хомоненко А. Д. "Delphi 6". – СПб.: БХВ-Петербург, 2002.
Н. Вирт. "Алгоритмы и структуры данных". – Электронное издание, 2003.
23
Скачать