- •Общие положения
- •Цель и задачи курсовой работы
- •Порядок выполнения
- •Требования к оформлению пояснительной записки
- •Краткие теоретические сведения
- •Основные определения теории графов
- •Способы представления графов в памяти эвм
- •Матрица смежностей графа
- •Матрица инцидентностей графа
- •Задание графа массивом преемников вершин (fo-представление графа)
- •Задание графа массивом предшественником вершин (fi-представление)
- •Модифицированное fo-представление графа (mfo-представление)
- •Модифицированное fi-представление графа (mfi-представление)
- •Сокращенные mfо и mfi-представления неорграфов
- •Нисходящее проектирование
- •Технология проектирования алгоритмов
- •Принципы нисходящего проектирования:
- •Варианты заданий для курсовой работы
- •Варианты расчетных заданий
- •Организация защиты курсовой работы
- •Постановка задачи
- •Входные данные
- •Аномалии
- •Функциональные тесты
- •Нисходящее проектирование
- •Основной алгоритм
- •Нисходящее проектирование на класcах
- •Методы public Kurs_Proekt ()
- •Библиографический список
- •Содержание
Нисходящее проектирование на класcах
Особенность нисходящего проектирования с классами заключается в том, что вначале необходимо определить требуемые классы с некоторыми очевидными членами класса (поля, свойства, методы и т.д.), которые в дальнейшем будут уточняться и детализироваться. В нашем случае можно выделить два класса: класс неориентированный граф (NеorGraf), в котором будут сосредоточены характеристики графа и методы его обработки, и класс курсовой проект (Kurs_Proekt), состоящий из двух графов, методов, обеспечивающих связь с внешним текстовым файлом, перепись с файла на экран и основного метода, в котором данные вводятся с файла либо с формы, затем вызываются методы построения характеристик графов, их сравнения и печать результатов сравнения. Ниже приведены начальные структуры этих классов.
Класс NeorGraf
{
Поля целое nv – количество вершин
целое mr - количество ребер
целое diametr – характеристика графа - диаметр
целое[,] MS – матрица смежности
Свойства public целое n – количество вершин
public целое m - количество ребер
Методы public NeorGraf():base(){}
}
Класс Kurs_Proekt
{
Поля NeorGraf gr1– первый граф
NeorGraf gr2– второй граф
String filename – внешнее имя текстового файла
StreamReader Potok-поток для считывания данных с
файла
Свойства
Методы public Kurs_Proekt ()
{
gr1 = new NeorGraf();
gr2 = new NeorGraf();
}
public void Sravnenie(bool fileEkran,OpenFileDialog
openFileDialog,NumericUpDown nUDn1,
NumericUpDown nUDm1,TextBox tBFO1,
NumericUpDown nUDn2,NumericUpDown nUDm2,
TextBox tBFO2)
{
//тело метода
}
}
Приступим к проектированию метода Sravnenie.
Для обработки ошибок будем использовать исключение.
public class MyExcept : ApplicationException
{
public MyExcept(string msg) : base(msg) { }
}
public void Sravnenie(bool fileEkran,OpenFileDialog
openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2,TextBox tBFO2)
НАЧАЛО
try//контроль переписи с файла и ввода с экрана
{
ЕСЛИ(fileEkran)ТО //данные на файле
ЕСЛИ(неподключение к файлу и создание потока)ТО
//в условии подзадача(1.1)
Вывод("Файл не выбран! Повторите ввод");
Выход
КЕСЛИ
try//контроль переписи с файла
{
перепись 1-го графа с частичным контролем
из файла на экран; (1.2)
перепись 2-го графа с частичным контролем
из файла на экран;
}
// обработка исключений при переписи с файла
catch (MyExcept e)
{
//здесь исключение вновь создается с
уточнением места ошибки
throw new MyExcept(e.Message + " с файла");
}
КЕСЛИ
try//контроль ввода с экрана
{
Ввод с экрана 1-го графа с полным контролем и
построением матрицы смежности MS1 (1.3)
Ввод с экрана 2-го графа с полным контролем и
построением матрицы смежности MS2
}
// обработка исключений при вводе с экрана
catch (MyExcept e)
{
//здесь исключение вновь создается с уточнением
места ошибки
throw new MyExcept(e.Message + " с экрана");
}
}
//обработка всех исключений
catch (MyExcept e)
{
Вывод(e.Message);
Выход;
}
Расчет диаметра графа 1(1.4)
Расчет диаметра графа 2
ЕСЛИ (характеристики равны(1.5)) ТО
Вывод("Графы эквивалентны");
ИНАЧЕ
Вывод("Графы не эквивалентны");
КЕСЛИ
КОНЕЦ
Из текста алгоритма видно, что в нем имеется 5 подзадач (1.1) –(1.5).
Дальнейшее проектирование можно выполнять двумя способами, которые были описаны ранее. Продолжаем проектирование вторым способом. Первые две подзадачи (метода) включим в класс Kurs_Proekt, а остальные - в класс NeorGraf, так как они свяаны с созданием и обработкой графов.
Реализация заглушки метода (1.1) – это подключение к файлу и создание потока.
public bool ConectFile(OpenFileDialog openFileDialog1)
{
MessageBox.Show("Подключение к файлу и создание
потока");
//return true;
return false;
}
Оставляя один из операторов return, можно создать ситуацию ошибки подключения к файлу.
Реализация заглушки метода (1.2) - перепись графа с частичным контролем из файла на экран.
public void Move_Gr_fileToEcran(NumericUpDown nUDn, NumericUpDown nUDm,TextBox tBFO
{
MessageBox.Show("Выполняется перенос графа с файла на экран");
throw new MyExcept("В данных на файле ошибка");
}
Комментируя или оставляя оператор throw, можно создать ситуацию ошибки при переписи с файла.
Реализация заглушки метода (1.3) - ввод с экрана графа с полным контролем и построением матрицы смежности MS1.
public void Input_GrInEkran(NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)
{
MessageBox.Show ("Выполняется ввод графа с экрана и построение
матрицы смежности");
throw new MyExcept ("В данных на форме ошибка");
}
Аналогично комментируя или оставляя оператор throw, можно создать ситуацию ошибки при вводе с экрана.
Реализация заглушки метода (1.4) - расчет диаметра графа.
public void Diametr()
{
MessageBox.Show("Расчет диаметра графа");
diametr = 2;
}
Реализация метода (1.5) - характеристики равны.
public bool Equals(NorGraf obj)
{
if (this.diametr == obj.diametr)
return true;
else
return false;
}
Подставим реализованные заглушки в метод Sravnenie.
public void Sravnenie(bool fileEkran,OpenFileDialog
openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2,TextBox tBFO2)
НАЧАЛО
try//контроль переписи с файла и ввода с экрана
{
ЕСЛИ(fileEkran)ТО //данные на файле
ЕСЛИ(!ConectFile(openFileDialog1)/*
неподключение к файлу и создание потока*/)ТО
Вывод("Файл не выбран! Повторите ввод");
Выход
КЕСЛИ
try//контроль переписи с файла
{
//перепись 1-го графа с частичным контролем
из файла на экран; (1.2)
Move_Gr_fileToEcran(nUDn1,nUDm1,tBFO1);
//перепись 2-го графа с частичным контролем
из файла на экран;
Move_Gr_fileToEcran(nUDn2,nUDm2,tBFO2);
}
// обработка исключений при переписи с файла
catch (MyExcept e)
{
//здесь исключение вновь создается с
уточнением места ошибки
throw new MyExcept(e.Message + " с файла");
}
КЕСЛИ
try//контроль ввода с экрана
{
//Ввод с экрана 1-го графа с полным контролем и
построением матрицы смежности MS1 (1.3)
gr1.Input_GrInEkran(nUDn1, nUDm1, tBFO1);
//Ввод с экрана 2-го графа с полным контролем и
построением матрицы смежности MS2
gr2.Input_GrInEkran(nUDn2, nUDm2, tBFO2);
}
// обработка исключений при вводе с экрана
catch (MyExcept e)
{
//здесь исключение вновь создается с уточнением
места ошибки
throw new MyExcept(e.Message + " с экрана");
}
}
//обработка всех исключений
catch (MyExcept e)
{
Вывод(e.Message);
Выход;
}
//Расчет диаметра графа 1(1.4)
gr1.Diametr();
//Расчет диаметра графа 2
gr2.Diametr();
ЕСЛИ (gr1.Equals(gr2)/*характер.равны(1.5)*/) ТО
Вывод("Графы эквивалентны");
ИНАЧЕ
Вывод("Графы не эквивалентны");
КЕСЛИ
КОНЕЦ
Записываем алгоритм Sravnenie на С# , создаем классы, включаем в классы методы и заглушки, вызываем метод Sravnenie и выполняем отладку.
public void Sravnenie(bool fileEkran,OpenFileDialog openFileDialog,NumericUpDown nUDn1, NumericUpDown nUDm1,TextBox tBFO1,NumericUpDown nUDn2,NumericUpDown nUDm2, TextBox tBFO2)
{
try//контроль переписи с файла и ввода с экрана
{
if (fileEkran)
{
if (!ConectFile(openFileDialog))//подключение к
файлу и создание потока (1.1)
{
MessageBox.Show("Файл не выбран! Повторите
ввод");
return;
}
try//контроль переписи с файла
{
//перепись 1-го графа с частичным контролем
из файла на экран; (1.2)
Move_Gr_fileToEcran(gr1.ng,nUDn1,nUDm1,tBFO1);
//перепись 2-го графа с частичным контролем
из файла на экран;
Move_Gr_fileToEcran(gr2.ng, nUDn2,nUDm2,tBFO2);
}
// обработка исключений при переписи с файла
catch (MyExcept e)
//здесь исключение вновь создается с уточнением
места ошибки
{
throw new MyExcept(e.Message + " с файла");
}
}
try//контроль ввода с экрана
{
//Ввод с экрана 1-го графа с полным контролем и
построением матрицы смежности MS1 (1.3)
gr1.Input_GrInEkran(nUDn1, nUDm1, tBFO1);
//Ввод с экрана 2-го графа с полным контролем и
построением матрицы смежности MS2
gr2.Input_GrInEkran(nUDn2, nUDm2, tBFO2);
}
// обработка исключений при вводе с экрана
catch (MyExcept e)
{
//здесь исключение вновь создается с уточнением
места ошибки
throw new MyExcept(e.Message + " с экрана");
}
}
//обработка всех исключений
catch (MyExcept e)
{
MessageBox.Show(e.Message);
return;
}
//Расчет диаметра графа 1(1.4)
gr1.Diametr();
//Расчет диаметра графа 2
gr2.Diametr();
if (gr1.Equals(gr2))//сравнение характеристик (1.5)
MessageBox.Show("Графы эквивалентны");
else
MessageBox.Show("Графы не эквивалентны")
}
Не забываем включить оператор создания экземпляра проекта
Kurs_Proekt KP = new Kurs_Proekt();
И в клике кнопки вызвать метод Sravnenie
KP.Sravnenie(radioButton1.Checked, openFileDialog1,nUDn1, nUDm1,
tBFO1,nUDn2, nUDm2, tBFO2);
Приступаем к проектированию подзадачи 1.1 - подключение к файлу и создание потока.
public bool ConectFile(OpenFileDialog openFileDialog1)
{
//Выбор файла и создание потока (1.1)
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
filename = openFileDialog1.FileName;
//создание потока и подсоединение к файлу
Potok = new StreamReader(filename);
return true;
}
else
return false;
}
Приступаем к проектированию подзадачи 1.2 - переписываем граф с файла на экран с частичным контролем.
public void Move_Gr_fileToEcran(NumericUpDown nUDn, NumericUpDown nUDm,TextBox tBFO)
НАЧАЛО
Перенос чисел n и m на форму в компоненты nUDn, nUDm.
Считываем строку с файла и преобразуем ее в вектор строк (vect)
В vect[0] будет n, а в vect[1] будет m (см. в спецификации размещение данных)
Выполняем контроль n и m и заносим их в компоненты nUDn и nUDm
Переносим FO на форму в компоненту tbFO ;
Считываем FO (может занимать несколько строк) с файла в строку S и преобразуем ее в вектор строк (vect), который переписываем в tbFO без контроля.
КОНЕЦ
В подзадаче 1.2 есть подзадачи, но они реализуются простыми средствами языка C#, без оформления их отдельными методами. Реализуем данную подзадачу на C#.
void Move_Gr_fileToEcran(int ng, NumericUpDown nUDn,
NumericUpDown nUDm,TextBox tBFO)
{
//Перенос чисел n и m на форму в компоненты
numericUpDown
//Считываем строку с файла и преобразуем ее в
вектор строк (veсt)
//В vect[0] будет n, а в vect[1] будет m (см.в
спецификации размещение данных)
char ch = ' ';
string str = Potok.ReadLine();
string[] vect = str.Split(ch);
int n, m;
try// контроль формата чисел
{
n = int.Parse(vect[0]);
m = int.Parse(vect[1]);
}
catch (FormatException e)
{
//добавим в класс графа поле целого типа ng,
//которое позволит уточнить, в каком графе ошибка
throw new MyExcept("В числах n или m
недопустимый символ в графе"+ ng.ToString());
}
//Выполняем контроль n и m и заносим их в
компоненты nUDn и nUDm
if ((n < 1) || (n > 20))
throw new MyExcept("Ошибка ввода количества вершин
графа " + ng.ToString());
nUDn.Value = n;
if ((m < 1) || (m > 50))
throw new MyExcept("Ошибка ввода количества ребер
графа " + ng.ToString());
nUDm.Value = m;
//Перенос FO на форму в компоненту tbFO
//Считываем FO(может занимать несколько строк) с
файла в строку S и преобразуем
// ее в вектор строк (vect), который переписываем
в tbFO без контроля
string strp = "";
while ((str = Potok.ReadLine()) != "")
strp += str;
vect = strp.Split(ch);
int k = vect.Length;
tBFO.Clear();
for (int i = 0; i < k - 1; i++)
tBFO.AppendText(vect[i] + "\r\n");
tBFO.AppendText(vect[k - 1]);
}
Методы 1.1 и 1.2 вставим вместо заглушек в класс Kurs_Proekt.
Приступаем к проектированию подзадачи 1.3 - ввод данных с экрана с контролем и построение матрицы смежности
Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)
НАЧАЛО
Считываем с экрана n, m;
n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal
m = (int)nUDm.Value ;
Проверка количества элементов FO
int k=tBFO.Lines.Length;
ЕСЛИ k<> n+2*m ТО
throw new MyExcept("Количество элементов FO
неверно в графе " + ng.ToString());
КЕСЛИ
Считываем FO и строим матрицу смежности (1.3.1)
Контроль симметричности матрицы смежности (1.3.2)
КОНЕЦ
В данном алгоритме есть две подзадачи - (1.3.1) и (1.3.2). Реализуем их в виде методов с логическим типом.
Реализация подзадачи (1.3.1) - считывание FO и построение матрицы смежности.
bool CreatMS(TextBox tBFO)
{
// создаем и обнуляем матрицу смежности
MS =new int[n,n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
MS[I,j]=0;
int L = 0;//индекс строки в компоненте tBFO
for (int i = 0; i < n; i++) //по вершинам графа
{
try //контроль формата чисел
{
// считываем первую вершину, следующую за i
int j = int.Parse(tBFO.Lines[L]);
//контроль j
if ((j < 0) || (j > n))
throw new MyExcept("Элемент FO - неверный в
графе "+ng.ToString());
//считываем остальные вершины, следующие за i
while (j != 0)
{
MS[i, j - 1] = 1;
L++;
j = int.Parse(tBFO.Lines[L]);
//контроль j
if ((j < 0) || (j > n))
throw new MyExcept ("Элемент FO - неверный
в графе " + ng.ToString());
}
L++;
}
catch (FormatException e)
{
throw new MyExcept ("В элементе FO недопустимый
символ в графе "+ng.ToString());
}
}
return true;
}
Реализация подзадачи (1.3.2) - контроль симметричности матрицы смежности.
bool SimetrMS(ref string msg)
{
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (MS[i, j] != MS[j, i])
msg = msg + "[(" + i.ToString() + "," +
j.ToString()+")и("+j.ToString()+","+
i.ToString()+")]";
if (msg != "")
return false;
else
return true;
}
Подставим подзадачи 1.3.1, 1.3.2 в подзадачу 1.3.
Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)
НАЧАЛО
Считываем с экрана n, m;
n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal
m = (int)nUDm.Value ;
Проверка количества элементов FO
int k=tBFO.Lines.Length;
ЕСЛИ k<> n+2*m ТО
throw new MyExcept("Количество элементов FO
неверно в графе " + ng.ToString());
КЕСЛИ
//Считываем FO и строим матрицу смежности(1.3.1)
CreatMS(TextBox tBFO)
//Контроль симметричности матрицы смежности(1.3.2)
string msg = "";
ЕСЛИ (!SimetrMS(ref msg))
throw new MyExcept("Проверьте ребра " + msg + " в
графе " + ng.ToString());
КЕСЛИ
КОНЕЦ
Запишем метод 1.3 на C# и включим все три метода в класс NeorGraf.
public void Input_GrInEkran(NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO)
{
//Считываем с экрана n, m;
n = (int)nUDn.Value;//преобразуем в целое, так как
Value типа decimal
m = (int)nUDm.Value;
// Проверка количества элементов FO
int k = tBFO.Lines.Length;
if (k != n + 2 * m)
throw new MyExcept("Количество элементов FO
неверно в графе " + ng.ToString());
//Считываем FO и строим матрицу смежности (1.3.1)
CreatMS(tBFO);
//Контроль симметричности матрицы смежности (1.3.2)
string msg = "";
if (!SimetrMS(ref msg))
throw new MyExcept("Проверьте ребра " + msg + " в
графе " + ng.ToString());
}
Переходим к проектированию подзадачи 1.4 - расчёт радиуса графа.
int Diametr()
НАЧАЛО
int r=1 ;
int[,] MR=new int[n,n] ;
int[,] B1=new int[n,n];
int[,] B2=new int[n,n] ;
bool pr =true;
копировать матрицу MS в MR(1.4.1)
копировать матрицу MS в В1
ПОКА pr ЦИКЛ
Pr=false;
r=r+1 ;
Умножение матриц В2=В1*MS(1.4.2)
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
ЕСЛИ (MR[I,j]=0) и (B2[I,j]<>0 ) ТО
MR[I,j]=r;
Pr=true;
КЕСЛИ
КЦИКЛ
КЦИКЛ
копировать матрицу B2 в В1
КЦИКЛ
Возврат r-1
КОНЕЦ
В данном алгоритме есть две подзадачи (1.4.1 и 1.4.2). Реализуем их.
Подзадача 1.4.1 - копирование матрицы.
CopyMatr(int [,] A ,ref int [,] B)
НАЧАЛО
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
B[I,j]=A[I,j];
КЦИКЛ
КЦИКЛ
КОНЕЦ
Подзадача 1.4.2 - умножение матриц С=А*В
MulMatr(int [,] A , int [,] B,ref int[,]C)
НАЧАЛО
int S;
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
S=0;
ДЛЯkj=1 ДО n ЦИКЛ
S=S+A[I,k]*B[k,j]
КЦИКЛ
C[I,j]=S;
КЦИКЛ
КЦИКЛ
КОНЕЦ
Обе подзадачи запишем на языке C# и подставим в алгоритм 1.4.
public void CopyMatr(int [,] A ,ref int [,] B)
{
for(int i=0;i< n; i++)
for(int j=0;j< n; j++)
B[i,j]=A[i,j];
}
public void MulMatr(int [,] A , int [,] B,ref int[,]C)
{
int S;
for(int i=0;i< n; i++)
for(int j=0;j< n; j++)
{
S=0;
for(int k=0;k< n; k++)
S=S+A[i,k]*B[k,j]
C[i,j]=S;
}
}
int Diametr()
НАЧАЛО
int r=1 ;
int[,] MR=new int[n,n] ;
int[,] B1=new int[n,n];
int[,] B2=new int[n,n] ;
bool pr =true;
//копировать матрицу MS в MR (1.4.1)
CopyMatr(MS ,ref MR)
// копировать матрицу MS в В1
CopyMatr(MS ,ref B1 )
ПОКА pr ЦИКЛ
pr=false;
r=r+1 ;
// Умножение матриц В2=В1*MS (1.4.2)
MulMatr(B1 , MS, ref B2)
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
ЕСЛИ (MR[I,j]=0) и (B2[I,j]<>0 ) ТО
MR[I,j]=r;
Pr=true;
КЕСЛИ
КЦИКЛ
КЦИКЛ
//копировать матрицу B2 в В1
CopyMatr(B2 ,ref B1)
КЦИКЛ
Возврат r-1
КОНЕЦ
Запишем алгоритм на C# и подставим его вместо заглушки 1.4.
public int Diametr()
{
int r=1 ;
int[,] MR=new int[n,n] ;
int[,] B1=new int[n,n];
int[,] B2=new int[n,n] ;
bool pr =true;
//копировать матрицу MS в MR (1.4.1)
CopyMatr(MS ,ref MR);
// копировать матрицу MS в В1
CopyMatr(MS ,ref B1 );
while ( pr)
{
pr=false;
r=r+1 ;
// Умножение матриц В2=В1*MS (1.4.2)
MulMatr(B1 , MS, ref B2);
for(int i=0; i< n; i++)
for(int j=0; j< n; j++)
if( (MR[i,j]==0) && (B2[i,j]!=0 ))
{
MR[i,j]=r;
pr=true;
}
//копировать матрицу B2 в В1
CopyMatr(B2 ,ref B1);
}
return r-1;
}
Включим все три метода в класс NeorGraf.
