Основной алгоритм
АЛГОРИТМ Курсовой_проект
<Описание переменных> (см. спецификацию)
НАЧАЛО
ЕСЛИ (ввод с файла) ТО
Выбор файла и создание потока (1.1)
перепись 1-го графа с частичным контролем из файла на экран; (1.2)
ЕСЛИ (ошибка) ТО
вывод («В данных на файле ошибка!»);
Выход;
КЕСЛИ
перепись 2-го графа с частичным контролем из файла на экран;
ЕСЛИ (ошибка) ТО
вывод («В данных на файле ошибка!»);
Выход;
КЕСЛИ
Закрыть поток.
КЕСЛИ
Ввод с экрана 1-го графа с полным контролем и построением матрицы смежности MS1 (1.3)
ЕСЛИ (ошибка) ТО
вывод («В данных на форме ошибка»)
Выход;
КЕСЛИ
Ввод с экрана 2-го графа с полным контролем и построением матрицы смежности
MS2
ЕСЛИ (ошибка) ТО
вывод («В данных на форме ошибка»)
Выход;
КЕСЛИ
Расчет диаметра 1-го графа d1 (1.4)
Расчет диаметра 2-го графа d2;
ЕСЛИ (d1=dr2) ТО
|
|
вывод («Графы эквивалентны»);
ИНАЧЕ
вывод («Графы не эквивалентны»);
КЕСЛИ
КОНЕЦ
Из текста алгоритма видно, что в нем имеется 4 подзадачи (рис.21).
Рис. 21
Дальнейшее проектирование можно выполнять двумя способами.
1-й способ
Продолжаем раскрывать содержание подзадач. Если в процессе раскрытия подзадачи на определенном уровне нет внутренних подзадач, то эту подзадачу подставляем в верхний уровень. Подстановка осуществляется следующим образом. Текст подзадачи превращаем в комментарий, а ниже располагаем вызов подзадачи с фактическими параметрами. Если все подзадачи нижнего уровня подставлены в верхние уровни, после этого записываем все алгоритмы на языке программирования и отлаживаем проект.
2-й способ
Подзадачи (1.1) – (1.4) реализуются «заглушками». Заглушка – это алгоритм (метод), написанный на языке программирования с правильным заголовком и с упрощенным либо пустым блоком. Указанные заглушки подставляем в основной алгоритм, а затем записываем на языке программирования и вместе с «заглушками» отлаживаем программу. После отладки детализируем отдельные подзадачи таким же способом.
Проектирование будем выполнять вторым способом. Напомним, что при проектировании подзадач имеется три варианта: реализация подзадачи в виде блока, в виде метода без типа и в виде метода с возвратом значения некоторого типа.
Реализация подзадачи (1.1). Выбор файла и создание потока (подзадачу реализуем в виде блока)
Программирование будем выполнять на языке C#.
Переменные
string filename;
{
if (openFileDialog1.ShowDialog == DialogResult.OK)
|
|
{
filename = openFileDialog1.FileName;
//создание потока и подсоединение к файлу
Potok = new StreamReader(filename);
}
else
{
MessageBox.Show(“Файл не выбран!”);
return;
}
Реализация подзадачи (1.2). Ввод графа с файла на экран с частичным контролем. Подзадачу реализуем в виде метода без типа.
Для размещения параметров графа n и m используем компоненты NumericUpDown, что позволяет уменьшить количество проверок, а для размещения FO – представления, компоненту TextBox. Для имитации ошибок данных, при переносе с файла, на форме временно разместим компоненты типа CheckBox (CB1, CB2).
public void Move_Gr_fileToEcran (StreamReader Potok, NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFО, ref bool error)
{
MessageBox.Show(“Выполняется перенос графа с файла на экран”);
error=CB1.Checked;
}
Реализация подзадачи (1.3). Ввод данных с экрана с контролем и построением матрицы смежности. Подзадачу реализуем в виде метода без типа.
public void Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO, ref int n, ref int m, ref int [,] MS, ref bool error)
{
MessageBox.Show (“Выполняется ввод графа с экрана и построение матрицы”);
error=CB2.Checked;
}
Реализация заглушки (1.4). Расчет диаметра графа. Подзадачу реализуем в виде метода с типом результата (целое число)
public int Diametr(int[,]MS)
{
MessageBox.Show(“Находим диаметр графа”);
return 2;
}
Подставляем «заглушки» в основной алгоритм
АЛГОРИТМ Курсовой_проект
<Описание переменных> (см. спецификацию)
string filename;
bool error;
НАЧАЛО
ЕСЛИ (ввод с файла) ТО
//Выбор файла и создание потока (1.1)
if (openFileDialog1.Show == DialogResult.OK)
{
filename = openFileDialog1.Filename;
//создание потока и подсоединение к файлу
StreamReader Potok = new StreamReader(filename);
}
else
{
MessageBox.Show(“Файл не выбран!”);
Return;
}
//перепись 1-го графа с частичным контролем из файла на экран; (1.2)
Move_Gr_fileToEcran (Potok, nUDn1, nUDm1, tBFО1, ref error);
ЕСЛИ (error) ТО
вывод («В данных на файле ошибка!»);
Выход;
КЕСЛИ
//перепись 2-го графа с частичным контролем из файла на экран;
Move_Gr_fileToEcran (Potok, nUDn1, nUDm1, tBFО1, ref error);
ЕСЛИ (error) ТО
вывод («В данных на файле ошибка!»);
Выход;
КЕСЛИ
Potok.Close();
КЕСЛИ
//Ввод с экрана 1-го графа с полным контролем и построением матрицы смежности //MS1 (1.3)
Input_GrInEkran (nUDn1, nUDm1, tBFO1, ref n1, ref m1, ref MS1, ref error);
ЕСЛИ (error) ТО
вывод («В данных на форме ошибка»)
Выход;
КЕСЛИ
//Ввод с экрана 2-го графа с полным контролем и построением матрицы смежности
// MS2
Input_GrInEkran (nUDn2, nUDm2, tBFO2, ref n2, ref m2, ref MS2, ref error);
ЕСЛИ (error)) ТО
вывод («В данных на форме ошибка»)
Выход;
КЕСЛИ
//Расчет диаметра 1-го графа r1 (1.4)
// Расчет диаметра 2-го графа r2;
ЕСЛИ (/*d1= d2*/ Diametr(MS1)== Radius(MS2)) ТО
вывод («Графы эквивалентны»);
ИНАЧЕ
вывод («Графы не эквивалентны»);
КЕСЛИ
КОНЕЦ
Записываем основной алгоритм на С# и вместе с заглушками отлаживаем его.
public void Kyrs_proekt()
{
<Описание переменных> (см. спецификацию)
string filename;
bool error;
if (/*ввод с файла*/radioGroup1.Checked)
{
//Выбор файла и создание потока (1.1)
if (openFileDialog1.Show == DialogResult.OK)
{
filename = openFileDialog1.Filename;
//создание потока и подсоединение к файлу
StreamReader Potok = new StreamReader(filename);
}
else
{
MessageBox.Show(“Файл не выбран!”);
Return;
}
//перепись 1-го графа с частичным контролем из файла на экран; (1.2)
Move_Gr_fileToEcran (Potok, nUDn1, nUDm1, tBFО1, ref error);
|
|
if (error)
{
MessageBox.Show (“В данных на файле ошибка!”);
return;
}
//перепись 2-го графа с частичным контролем из файла на экран;
Move_Gr_fileToEcran (Potok, nUDn1, nUDm1, tBFО1, ref error);
if (error)
{
MessageBox.Show (“В данных на файле ошибка!”);
return;
}
Potok.Close();
}
//Ввод с экрана 1-го графа с полным контролем и построением матрицы смежности //MS1 (1.3)
Input_GrInEkran (nUDn1, nUDm1, tBFO1, ref n1, ref m1, ref MS1, ref error);
if (error)
{
MessageBox.Show (“В данных на форме ошибка”);
return;
}
//Ввод с экрана 2-го графа с полным контролем и построением матрицы смежности
// MS2
Input_GrInEkran (nUDn2, nUDm2, tBFO2, ref n2, ref m2, ref MS2, ref error);
if (error))
{
MessageBox.Show (“В данных на форме ошибка”);
return;
}
//Расчет диаметра 1-го графа r1 (1.4)
// Расчет диаметра 2-го графа r2;
if (/*d1= d2*/ Diametr(MS1)== Radius(MS2))
MessageBox.Show (“Графы эквивалентны”);
else
MessageBox.Show (“Графы не эквивалентны”);
}
Приступаем к проектированию подзадачи (1.2). Перепись графа с файла на экран с частичным контролем.
Move_Gr_fileToEcran (StreamReader Potok. NumericUpDown nUDn, NumericUpDown nUDm, TextBox tbFO, ref bool error)
НАЧАЛО
Перенос чисел n и m на форму в компоненты nUDn, nUDm.
Считываем строку с файла и преобразуем ее в вектор строк (vect).
В vect[0] будет n, а в vect[1] будет m (см. в спецификации размещение данных).
Выполняем контроль n и m и заносим их в компоненты nUDn и nUDm.
Перенос FO на форму в компоненту tbFO.
Считываем FO (может занимать несколько строк) с файла в строку S и преобразуем ее в вектор строк (vect), который переписываем в tbFO без контроля.
КОНЕЦ
В этой подзадаче есть подзадачи, но они реализуются простыми средствами языка C#, без оформления их отдельными методами.
Реализуем данную подзадачу на C#.
public void Move_Gr_fileToEcran (StreamReader Potok. NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO, ref bool error)
{
//Перенос чисел n и m на форму в компоненты numericUpDown.
//Считываем строку с файла и преобразуем ее в вектор строк (vekt).
//В vect[0] будет n, а в vect[1] будет m (см. в спецификации размещение данных)
|
|
har ch= ‘ ‘;
string str =Potok.ReadLine();
string [] vect=str.split();
n = int.Parse(vect[0]);
m = int.Parse(vect[1]);
//Выполняем контроль n и m и заносим их в компоненты nUDn и nUDm
if((n < 1) || (n > 20))
{
MessageBox.Show ("Ошибка ввода количества вершин графа");
error = true;
return;
}
nUDn.Value = n;
if ((m < 1) || (m > 50))
{
MessageBox.Show ("Ошибка ввода количества ребер графа");
error = true;
return;
}
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;i++)
tBFO.Lines[i]=vect[i];
}
Этот метод записываем вместо заглушки (1.2).
Приступаем к проектированию подзадачи (1.3). Ввод данных с экрана с контролем и построением матрицы смежности
Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO, ref int n, ref int m, ref [,] MS, ref bool error)
НАЧАЛО
Считываем с экрана n, m;
n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal
m = (int)nUDm.Value;
Проверка количества элементов FO.
int k=tBFO.Lines.Length;
ЕСЛИ k<> n+2*m ТО
Вывод (“Количество элементов FO неверно”);
error=true;
Выход;
КЕСЛИ
//обнуляем матрицу смежности
ДЛЯ i = 1 ДО n ЦИКЛ
ДЛЯ j = 1 ДО n ЦИКЛ
MS [i,j]=0;
КЦИКЛ
КЦИКЛ
Считываем FO и строим матрицу смежности (1.31 на рис. 22).
Контроль симметричности матрицы смежности (1.32 на рис. 22).
КОНЕЦ
Рис. 22
В этом алгоритме есть две подзадачи (1.31) и (1.32). Реализуем их в виде методов с типом.
Реализация подзадачи (1.31) - считывание FO и построение матрицы смежности.
bool CreatMS(TextBox tBFO,ref int [,] MS)
НАЧАЛО
L=0;//индекс строки в компоненте tBFO
int n =(int)Math.Sqrt(MS.Length);
ДЛЯ i = 1 ДО n ЦИКЛ //по вершинам графа
// считываем первую вершину j, следующую за i
j = int,Parse(tBFO.Lines [L]);
//контроль j
ЕСЛИ (j<0) или (j>n) ТО
Вывод («Элемент FO - неверный»);
Выход true;
КЕСЛИ
//считывание остальных вершин j, следующих за i
ПОКА (j <>0) ЦИКЛ
MS[i,j]:=1;
L=L+1;
j = int.Parse(tBFO.Lines [L]);
//контроль j
ЕСЛИ (j<0) или (j>n) ТО
Вывод («Элемент FO - неверный»);
Выход true;
КЕСЛИ
КЦИКЛ
L=L+1;
КЦИКЛ
Выход false
КОНЕЦ
Реализация подзадачи (1.32) – проверка симметричности матрицы смежности.
bool SimetrMS(int [,] MS,ref string msg)
НАЧАЛО
int n =(int)Math.Sqrt(MS.Length);
msg=””;
ДЛЯ i = 1 ДО n ЦИКЛ
ДЛЯ j = i+1 ДО n ЦИКЛ
ЕСЛИ MS [i,j]<> MS [j,i] ТО
msg =msg +”[“+значения(I,j и j,i)+”]”;
КЕСЛИ
ЕСЛИ msg<>”” ТО
msg =”Проверить ребра ”+msg
Выход true;
ИНАЧЕ
Выход false;
КЕСЛИ
КОНЕЦ
В подзадачах (1.31) и (1.32) нет других подзадач. Запишем их на C# и подставим в подзадачу (1.3).
public bool CreatMS(TextBox tBFO,ref int [,] MS)
{
int L=0;//индекс строки в компоненте tBFO
int n=(int)Math.Sqrt(MS.Length);
for(int i = 0; i< n; i++) //по вершинам графа
{
// считываем первую вершину j, следующую за i
j = int,Parse(tBFO.Lines [L]);
//контроль j
If((j<0) || (j>n))
{
MessageBox.Show («Элемент FO - неверный»);
return false;
}
//считывание остальных вершин j, следующих за i
while(j <>0)
{
MS[i,j-1]:=1;
L++;
j = int.Parse(tBFO.Lines [L]);
//контроль j
If((j<0) || (j>n))ТО
{
MessageBox.Show («Элемент FO - неверный»);
return false;
}
}
L=L+1;
}
return true;
}
public bool SimetrMS(int [,] MS,ref string msg)
{
int n=(int)Math.Sqrt(MS.Length);
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!=””)
{
msg =”Проверить ребра ”+msg;
return false;
}
else
return true;
}
На рис. 23 отобразим записанные задачи на C#:
Рис. 23
Подставляем эти задачи в подзадачу (1.3):
Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO, ref int n, ref int m, ref [,] MS, ref bool error)
НАЧАЛО
Считываем с экрана n, m.
n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal
m = (int)nUDm.Value;
Проверка количества элементов FO.
int k=tBFO.Lines.Length;
ЕСЛИ k<> n+2*m ТО
Вывод (“Количество элементов FO неверно”);
error=true;
Выход;
КЕСЛИ
//обнуляем матрицу смежности
ДЛЯ i = 1 ДО n ЦИКЛ
ДЛЯ j = 1 ДО n ЦИКЛ
MS [i,j]=0;
КЦИКЛ
КЦИКЛ
//Считываем FO и строим матрицу смежности (1.31)
ЕСЛИ не CreatMS(tBFO,ref MS) ТО
error=true
Выход
КЕСЛИ
//Контроль симметричности матрицы смежности (1.32)
string msg=””;
ЕСЛИ не SimetrMS(MS,ref msg)ТО
Вывод (msg);
error=true;
Выход;
КЕСЛИ
КОНЕЦ
Записываем подзадачу (1.3) на C#, подставляем ее вместо заглушки (1.3) и отлаживаем основной алгоритм.
public void Input_GrInEkran (NumericUpDown nUDn, NumericUpDown nUDm, TextBox tBFO, ref int n, ref int m, ref int [,] MS, ref bool error)
{
//Считываем с экрана n, m.
n =(int) nUDn.Value;//преобразуем в целое, так как Value типа decimal
m = (int)nUDm.Value;
// Проверка количества элементов FO.
int k=tBFO.Lines.Length;
if (k!= n+2*m)
{
MessageBox.Show (“Количество элементов FO неверно”);
error=true;
return;
}
//обнуляем матрицу смежности
f or(int i = 0; i< n; i++)
for(int j = 0; j< n; j++)
MS [i,j]=0;
//Считываем FO и строим матрицу смежности (1.31)
if(!CreatMS(tBFO,ref MS))
{
error=true;
return;
}
//Контроль симметричности матрицы смежности (1.32)
string msg=””;
if(!SimetrMS(MS,ref msg))
{
MessageBox.Show (msg);
error=true;
return;
}
}
Переходим к проектированию подзадачи (1.4). Расчёт диаметра графа.
int Radius(int[,]MS)
НАЧАЛО
int n =(int)Math.Sqrt(MS.Length);
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=MS(1.41)
копировать матрицу MS в В1=MS
ПОКА pr ЦИКЛ
Pr=false;
r=r+1;
Умножение матриц В2=В1*MS(1.42)
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
ЕСЛИ (MR[I,j]=0) и (B2[I,j]<>0) ТО
MR[I,j]=r;
Pr=true;
КЕСЛИ
КЦИКЛ
КЦИКЛ
копировать матрицу B2 в В1=B2
КЦИКЛ
Возврат r-1
КОНЕЦ
Рис. 24
В данном алгоритме есть две подзадачи (рис. 24). Реализуем их.
Подзадача (1.4.1) - копирование матрицы.
CopyMatr(int [,] A,ref int [,] B)
НАЧАЛО
Int n =(int)Math.Sqrt(A.Length);
ДЛЯ i=1 ДО n ЦИКЛ
ДЛЯ j=1 ДО n ЦИКЛ
B[I,j]=A[I,j];
КЦИКЛ
КЦИКЛ
КОНЕЦ
Подзадача (1.4.2) - умножение матриц С=А*В
MulMatr(int [,] A, int [,] B,ref int[,]C)
НАЧАЛО
int n =(int)Math.Sqrt(A.Length);
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)
{
iInt n =(int)Math.Sqrt(A.Length);
for(int i=0;i< n; i++)
for(intji=0;j< n; j++)
B[i,j]=A[i,j];
}
public void MulMatr(int [,] A, int [,] B,ref int[,]C)
{
int n =(int)Math.Sqrt(A.Length);
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;
}
}
На рис. 25 отобразим записанные задачи на C#:
Рис. 25
Подставляем задачи в алгоритм (1.4).
int Diametr(int[,]MS)
НАЧАЛО
int n =(int)Math.Sqrt(MS.Length);
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=MS(1.41)
CopyMatr(MS,ref MR)
// копировать матрицу MS в В1=MS
CopyMatr(MS,ref B1)
ПОКА pr ЦИКЛ
pr=false;
r=r+1;
// Умножение матриц В2=В1*MS(1.42)
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=B2
CopyMatr(B2,ref B1)
КЦИКЛ
Возврат r-1;
КОНЕЦ
Запишем алгоритм на C# и подставим его вместо заглушки (1.4).
public int Diametr(int[,]MS)
{
int n =(int)Math.Sqrt(MS.Length);
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=MS(1.41)
CopyMatr(MS,ref MR)
// копировать матрицу MS в В1=MS
CopyMatr(MS,ref B1)
while (pr)
{
pr=false;
r=r+1;
// Умножение матриц В2=В1*MS(1.42)
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=B2
CopyMatr(B2,ref B1)
}
return r-1
}
Окончательный проект (рис. 26):
Рис. 26