дискретка_все_практики / дискретка / Razdel_5_Praktika_11
.doc8.
|
A |
B |
C |
D |
E |
F |
G |
A |
0 |
3 |
1 |
5 |
10 |
5 |
6 |
B |
3 |
0 |
5 |
3 |
1 |
8 |
6 |
C |
1 |
5 |
0 |
1 |
5 |
1 |
2 |
D |
5 |
3 |
1 |
0 |
3 |
3 |
3 |
E |
10 |
1 |
5 |
3 |
0 |
4 |
5 |
F |
5 |
8 |
1 |
3 |
4 |
0 |
1 |
G |
6 |
6 |
2 |
3 |
5 |
1 |
0 |
9.
|
A |
B |
C |
D |
E |
F |
G |
A |
0 |
3 |
1 |
5 |
7 |
9 |
6 |
B |
3 |
0 |
5 |
3 |
1 |
8 |
6 |
C |
1 |
5 |
0 |
6 |
5 |
1 |
2 |
D |
5 |
3 |
6 |
0 |
3 |
7 |
3 |
E |
7 |
1 |
5 |
3 |
0 |
1 |
5 |
F |
9 |
8 |
1 |
7 |
1 |
0 |
1 |
G |
6 |
6 |
2 |
3 |
5 |
1 |
0 |
10.
|
A |
B |
C |
D |
E |
F |
G |
A |
0 |
4 |
1 |
5 |
7 |
5 |
6 |
B |
4 |
0 |
5 |
3 |
2 |
8 |
9 |
C |
1 |
5 |
0 |
1 |
5 |
1 |
2 |
D |
5 |
3 |
1 |
0 |
3 |
3 |
8 |
E |
7 |
2 |
5 |
3 |
0 |
1 |
5 |
F |
5 |
8 |
1 |
3 |
1 |
0 |
1 |
G |
6 |
9 |
2 |
8 |
5 |
1 |
0 |
3.2 Задания для вычисления с помощью программы:
Задан полный граф с длинами ребер. Построить для него граф наименьшей длины, используя известную среду программирования.
4. МЕТОДИЧЕСКИЕ УКАЗАНИЯ
Описание алгоритма Краскала на псевдокоде:
T <- пустое множкство;
VS <- пустое множество;
Построить очередь с приоритетами Q, содержащую все ребра из E;
for (v принадлежащего V) Добавить {v} к VS
while |VS|>1
{
Выбрать в Q ребро (v,w) наименьшей стоимости;
Удалить (v,w) из Q;
if v и w принадлежат различным множествам W1 и W2 из VS
{
Заменить W1 и W2 на объединение W1 и W2 в VS;
Добавить (v,w) к T;
}
}
Реализуем алгоритм на языке C++. Для хранения ребер и их стоимостей воспользуемся бинарным деревом поиска, описание которого имеет вид:
typedef unsigned int SubInt;
typedef struct Uzel *Ref;
typedef struct Uzel
{
SubInt X; //Начало дуги.
SubInt Y; //Конец дуги
int Pay; //Стоимость дуги.
Ref Left; //Указатель на левого сына.
Ref Right;//Указатель на правого сына.
};
Ясно, что в "самой левой" вершине дерева будет храниться дуга, обладающая наименьшей стоимостью, и поиск этой вершины может выглядеть, например, так:
UkUzel = Root; //Установили текущий указатель на корень дерева.
while (UkUzel->Left != NULL)
UkUzel = UkUzel->Left;
T1 = UkUzel->X; T2 = UkUzel->Y; //Получили ребро!
Множество VS будем хранить в линейном однонаправленном списке с заглавным звеном, описание которого выглядит так:
typedef struct zveno *svqz;
typedef struct zveno
{
unsigned int Element[256]; // Множество из VS.
svqz Sled; // Указатель на узел.
zveno(); // Конструктор.
};
zveno::zveno()
//Обнуление элементов.
{
for(int k=0;k<256;Element[k++]=0);
}
Тогда, например, фрагмент алгоритма:
if v и w принадлежат различным множествам W1 и W2 из VS
{
Заменить W1 и W2 на объединение W1 и W2 в VS;
Добавить (v,w) к T;
}
запишется на языке С++ так:
Res1 = Res2 = NULL;
Poisk (UkStr,T1,&Res1);
Poisk (UkStr,T2,&Res2);
if ( Res1!=Res2 )
{
for (int k=0;k<256;k++)
if ( Res1->Element[k]==1 || Res2->Element[k]==1 ) Res1->Element[k]=1;
Udalenie (&Res2,UkStr);
cout << "(" << T1 << " " << T2 << ") ";
}
Пример. Построение графа наименьшей длины (алгоритм Краскала).
#include <iostream.h>
#define TRUE 1
#define FALSE 0
typedef int Boolean;
typedef unsigned int SubInt;
typedef struct Uzel *Ref;
typedef struct Uzel
{
SubInt X; //Начало дуги.
SubInt Y; //Конец дуги
int Pay; //Стоимость дуги.
Ref Left; //Указатель на левого сына.
Ref Right;//Указатель на правого сына.
};
typedef struct zveno *svqz;
typedef struct zveno
{
unsigned int Element[256];
svqz Sled;
zveno();
};
zveno::zveno()
{
for(int k=0;k<256;Element[k++]=0);
}
class Spisok
{
private:
Ref Root;
void Search (int, int, int, Ref *);
void Poisk (svqz, SubInt, svqz *);
void Postroenie (svqz *);
void Udalenie (svqz *, svqz);
public:
Spisok() { Root = NULL;} //Вначале дерево пусто.
void Reshenie();
void Postr();
};
void Spisok::Search (int A, int B, int C, Ref *p)
//Добавление вершины, содержащей поля A,B,C, в дерево *p.
{
if ( (*p) == NULL )
{
(*p) = new (Uzel); (**p).X = A; (**p).Y = B; (**p).Pay = C;
(**p).Left = (**p).Right = NULL;
}
else
if ( C<=(**p).Pay ) Search (A,B,C,&((**p).Left));
else
if ( C>(**p).Pay ) Search (A,B,C,&((**p).Right));
}
void Spisok::Postroenie (svqz *UkStr)
//Постpоение линейного однонапpавленного списка
//с заглавным звеном, содержащего вершины графа.
{
svqz UkZv;
int el;
(*UkStr) = new (zveno);
UkZv = (*UkStr); UkZv->Sled = NULL;
cout << "Вводите вершины графа: \n";
cin >> el;
while ( el!=0 )
{
UkZv->Sled = new (zveno); UkZv = UkZv->Sled;
UkZv->Element[el] = 1; UkZv->Sled = NULL;
cin >> el;
}
}
void Spisok::Postr()
//Постpоение деpева, содержащего все ребра графа.
{
int A,B,C;
cout << "Для каждого ребра вводите начальную, затем конечную\n";
cout << "вершины и стоимость ребра, их соединяющего:\n";
cin >> A >> B >> C;
while ( A!=0 )
{ Search (A,B,C,&Root);
cin >> A >> B >> C;
}
}
void Spisok::Poisk (svqz st, SubInt MENT, svqz *Res)
{
svqz q;
(*Res) = NULL; q = st->Sled;
while ( q != NULL && (*Res) == NULL )
{
if ( q->Element[MENT]==1 ) (*Res) = q;
else q = q->Sled;
}
}
void Spisok::Udalenie (svqz *zv, svqz UkStr)
//Удаление из однонапpавленного списка с заглавным звеном
//элемента, на который указывает указатель zv.
{
svqz Z; //"Стаpый" указатель.
svqz UkZv1; //"Hовый" указатель.
if ( (*zv)->Sled != NULL ) (**zv) = *((**zv).Sled);
else
{ Z = UkStr; UkZv1 = UkStr->Sled;
while (UkZv1 != (*zv))
{ Z = UkZv1; UkZv1 = UkZv1->Sled; }
Z->Sled = NULL; delete UkZv1;
}
}
void Spisok::Reshenie()
{
svqz UkStr; //Указатель на список.
Ref UkUzel; //Рабочий указатель на узел дерева.
Ref UkUzel1; //Рабочий указатель на узел дерева.
SubInt T1,T2;
svqz Res1,Res2;
//Построение первоначальных множеств вершин графа.
Postroenie (&UkStr);
cout <<"Ребра экономического дерева: ";
while ( UkStr->Sled->Sled != NULL )
{
UkUzel1 = Root; //"Отстающий" указатель.
UkUzel = Root->Left; //"Опережающий" указатель.
if ( UkUzel== NULL )
{ //Выбор в дереве ребра наименьшей стоимости и ...
T1 = Root->X; T2 = Root->Y;
//... удаление этого ребра из дерева.
Root = Root->Right; delete UkUzel1;
}
else
{ //Выбор в дереве ребра наименьшей длиныи и ...
while ( UkUzel->Left != NULL )
{
UkUzel1 = UkUzel1->Left;
UkUzel = UkUzel->Left;
}
T1 = UkUzel->X; T2 = UkUzel->Y;
//... удаление этого ребра из дерева.
UkUzel1->Left = UkUzel->Right;
delete UkUzel;
}
//Если v и w принадлежат различным
//множествам W1 и W2 из VS ...
Res1 = Res2 = NULL;
Poisk (UkStr,T1,&Res1);
Poisk (UkStr,T2,&Res2);
if ( Res1!=Res2 )
{
for (int k=0;k<256;k++)
if ( Res1->Element[k]==1 || Res2->Element[k]==1 )
Res1->Element[k]=1;
Udalenie (&Res2,UkStr);
cout << "(" << T1 << " " << T2 << ") ";
}
}
}
void main ()
{
Spisok Tree;
Tree.Postr();
Tree.Reshenie();
}
Алгоритм поиска графа наименьшей длины методом Краскала
5. СОДЕРЖАНИЕ ОТЧЕТА
-
наименование работы, постановку задачи;
-
выбранный вариант задания;
-
результаты решения задач без применения ЭВМ;
-
программу решения задачи (представляется в электронном виде);
-
результаты работы программы и их анализ.
6. КОНТРОЛЬНЫЕ ВОПРОСЫ
-
Сформулируйте задачу о построении графа наименьшей длины на примере построения автомобильных дорог.
-
Дайте определение дерева.
-
Дайте определение ациклическому графу.
-
Почему граф наименьшей длины всегда является деревом?
-
Какое дерево называется экономическим?
-
Опишите алгоритм построения графа наименьшей длины.
-
Кем был предложен данный алгоритм?
-
Пользуясь данными таблицы 1, постройте граф наименьшей длины и найдите сумму длин ребер полученного экономического дерева.
-
Каковы этапы алгоритма построения остова наименьшей стоимости? тождественен ли он алгоритму Краскала?
7. ОСНОВНАЯ ЛИТЕРАТУРА
-
А. А. Зыков Основы теории графов – М., Наука, 1987. – 380, [1] с. кл.; 23 см.
-
А. И. Белоусов Дискретная математика: Учеб. пособие для втузов/Белоусов А. И., Ткачев С. Б., Под ред. Зарубина В. С., Ирищенко А. П. – 3-е изд., стер. – М.: Изд-во МГТУ им. Баумана, 2004. – 743 с.
-
О. П. Кузнецов, Г. М. Адельсон-Вельский «Дискретная математика для инженера». - М.: Энергоатомиздат, 1988 – 479, [1] с.: кл., 22 см.
-
Горбатов В. А. Дискретная математика: Учеб. для втузов В. А. Горбатов. – М.АСТ; Астель, 2003 – 447с (Высшая школа)
ДОПОЛНИТЕЛЬНАЯ ЛИТЕРАТУРА
1. М. С. Спирина, П. А. Спирин, «Дискретная математика»
Издательство: Академия, 2009 г., 368 стр.
2.Н. И. Костюкова, «Графы и их применение. Комбинаторные алгоритмы для программистов»
Издательства: Интернет-университет информационных технологий, Бином. Лаборатория знаний, 2007 , 312 стр.
3. В. Ф. Пономарев «Дискретная математика для инженеров»
Издательство: Горячая Линия - Телеком, 2009 г. Мягкая обложка, 320 стр.
4. Ю. П. Шевелев, «Дискретная математика»
Издательство: Лань, 2008 г, 592стр.