Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы объектно-ориентированного программирования задач на графах. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
6.3. Унарная функция-операция для проверки смежности двух вершин графа
51
но, и имена переменных, соответствующих номерам двух вершин, во всех функциях класса должны быть изменены, т.е. замените x11 на x1, а x22 на
x2. Изменим и главную функцию для вызова рассмотренных функций­операций:
//---------------------------------------------------­#pragma argsused int main() { int number; int x1,x2; cin>>number;
My_Class * graph = new My_Class(number); +(*graph); // ввод матрицы смежности графа
-(*graph); // вывод матрицы смежности графа cout<<" Input number of two tops: "; cin>>x1>>x2; graph->adjacency(x1,x2); graph->Graph::adjacency(x1,x2);
*(*graph); //ввод номеров двух вершин cout<< endl<<" Tops ";
// проверка смежности двух вершин
if( !(*graph)) cout<<" Adjacent"; else cout<< " No Adjacent";
delete graph; getch(); return 0; } //----------------------------------------------------
Перегрузка операции (!) демонстрирует также возможность возвращения значения функциями-операциями.
6. Задачи на графах и перегрузка операций
52
6.4. Перегрузка операций для виртуальных функций
Как быть в случае, если необходимо перегрузку операций использо-
вать для виртуальных функций? В нашем примере виртуальные функции adjacency() в классах Graph и My_Class, имеющие два аргумента, заменим функциями-операциями operator++() без аргументов, анало­гично тому, как это было сделано в предыдущем примере для функции­операции для определения смежности двух вершин. Замените объявление виртуальной функции
virtual void adjacency(int,int);
в описании класса Graph на
virtual void operator++();
а объявление витуальной функции
void adjacency(int,int);
в описании класса My_Class на
void operator++();
Замените также заголовки в определении виртуальных функций. В резуль­тате получим описания классов Graph и My_Class, содержащие вирту­альные функции-операции operator++(). В классе Graph виртуальная функция-операция operator++() определяет вершины графа, смежные хотя бы одной из двух заданных вершин графа. В классе My_Class вир­туальная функция-операция operator++() определяет вершины графа, смежные одновременно каждой из двух заданных вершин графа. До­бавьте в главную функцию операторы для ввода номеров двух вершин:
*(*graph);
и вызова функции-операции operator++() с помощью перегруженной опе­рации (++):
++(*graph);
Если запустить программу на выполнение, то результатом примене-
ния перегруженной операции (++) к объекту класса My_Class будет вы-
6.4. Перегрузка операций для виртуальных функций
53
звана последняя в иерархии классов Graph и My_Class виртуальная функция-операция operator++(), т.е. функция-операция operator++() из класса My_Class. На экран будут выведены номера вершин графа, смежные одновременно каждой из двух заданных вершин графа.
Но как быть, если требуется вызвать виртуальную функцию­операцию operator++() с помощью перегруженной операции (++) из класса Graph? Это сделать не удастся. Вызвать виртуальную функцию­операцию operator++() из базового класса можно только обычным вы­зовом виртуальной функции класса:
graph->Graph::operator++();
В результате главная функция будет иметь вид:
int main()
{ int number; cin>>number; My_Class * graph = new My_Class(number); +(*graph); // ввод матрицы смежности графа
-(*graph); // вывод матрицы смежности графа *(*graph); //ввод номеров двух вершин
++(*graph); graph->Graph::operator++();
*(*graph); //ввод номеров двух вершин cout<< endl<<" Tops "; if( !(*graph)) cout<<" Adjacent"; else cout<< " No Adjacent"; delete graph; getch(); return 0; }
Полный текст программы, в которой все функции классов Graph и My_Class оформлены с использованием перегрузки операций, приведен в
прил. 4.
6. Задачи на графах и перегрузка операций
54
6.5. Результат выполнения программы для унарных операций
На рис. 11 приведен результат работы программы для графа
(см. рис. 6). Начало ввода данных осталось за пределами окна.
Рис. 11. Результат работы программы для графа (см. рис. 6)
6.6. Бинарные функции-операции
Бинарная функция-операция создается для двух операндов. Один
операнд должен быть обязательно объектом класса. Второй операнд может быть объектом того же класса, что и первый операнд, или данным встроен­ного типа.
Бинарная функция-операция должна иметь один обязательный аргу-
мент. Тип этого аргумента зависит от того, какой второй операнд образует эту операцию. Если бинарная функция-операция класса создается для двух объектов одного и того же класса, то аргумент должен быть ссылкой или указателем на объект этого же класса. Если вторым операндом является встроенный тип данных, то тип аргумента должен совпадать с типом вто­рого операнда.
Зачем нужен обязательный аргумент? Дело в том, что функция­операция – это функция класса. Как и каждой функции класса, ей неявно передается указатель this на первый объект, который образует бинар-
6.7. Бинарная функция-операция для определения вершин, смежных заданной…
55
ную операцию. Этот указатель обеспечит доступ к данным и функциям объекта класса, соответствующего первому операнду. Доступ к членам второго операнда (объекта класса или данного встроенного типа) функция­операция получит только через обязательный аргумент.
6.7. Бинарная функция-операция для определения вершин, смежных заданной вершине графа
Для решения задач на графах создадим две новые функции-операции:
вывода на экран номеров вершин, смежных заданной вершине, и объеди­нения двух графов с одинаковым числом вершин. Для первой задачи пере­грузим операцию сравнения (>), а для второй задачи – логическую опера­цию «ИЛИ» (||).
Прототип функции-операции
void operator>(int);
первой задачи добавьте в описание класса My_Class:
class My_Class : public Graph { public: void operator*(); //ввод номеров двух //вершин int operator!(); //проверка смежности двух
//вершин
My_Class(int a ):Graph(a){} void operator++(); void operator>(int); };
Определение этой функции сделайте вне класса:
void My_Class::operator>(int x) { cout<<" Set of Tops adjacent top "<<x<<": {"; for(int i=0; i<N; i++)
6. Задачи на графах и перегрузка операций
56
if(Matr[x-1][i]) cout<<" "<<i+1<<","; cout<<" }"; }
Функция-операция имеет один аргумент – целое число, соответству-
ющее номеру вершины, для которой требуется определить вершины с ней смежные.
В главную функцию добавьте операторы:
//------- вершины смежные с заданной вершиной -------
cout<<endl<<"Input number of tops: "; int x1; cin>>x1; (*graph)>x1; //бинарная операция (>)
Обратите внимание, что в бинарной перегруженной операции (>)
(*graph)>x1;
для объекта класса My_Class первым должен быть обязательно располо­жен операнд – объект класса My_Class, а вторым – данное встроенного целого типа.
6.8. Бинарная функция-операция для объединения двух графов
Объединение графов – это операция над графами, в результате кото-
рой получается граф, множества вершин и рёбер которого являются объ­единениями множеств вершин и рёбер исходных графов, т.е. в результиру­ющий граф входят все рёбра и вершины, которые присутствуют в исход­ных графах.
Для обединения двух графов потребуется создать два объекта класса,
которые будут задавать исходные графы. В каждом объекте класса будет функция объединения двух графов. Тогда возникает необходимость пере­дачи одного объекта в функцию объединения графа, того объекта, для ко­торого эта функция будет вызываться.
6.8. Бинарная функция-операция для объединения двух графов
57
В С++ объекты классов передаются в функции классов через указа-
тель или ссылку на объект класса. Рассмотрим способ передачи объектов классов в функции классов посредством указателя на объект класса.
Создадим перегруженную функцию-операцию для объединения двух графов. Для этого добавим в описание класса My_Class прототип функ­ции-операции operator||():
void operator||(My_Class *);
Обратите внимание, что функция-операция имеет обязательный ар­гумент – указатель на объект класса My_Class.
Выбор знака встроенной операции || (побитовой операции вклю­чающего «ИЛИ»), связан исключительно с ассоциациями, которые возни­кают при рассмотрении операции объединения двух графов.
Определение этой функции сделайте вне класса:
//---функция вывода на экран объединения двух графов
void My_Class :: operator||(My_Class * graph_2) {
//выделение динамической памяти для матрицы смежности
//объединенного графа
bool **union_matr; union_matr=new bool *[N]; for(int i=0; i<N;i++) union_matr[i]= new bool [N];
//построение матрицы смежности объединенного графа
for(int i=0; i<N; i++) for(int j=0; j<N; j++) if(Matr[i][j]||graph_2->return_ij(i,j)) union_matr[i][j]=1; else union_matr[i][j]=0;
//вывод на экран матрицы смежности объединенного графа cout<<endl<<"Matrix of Union Graph";
6. Задачи на графах и перегрузка операций
58
for(int i=0; i<N; i++) { cout<<endl; for(int j=0; j<N; j++) cout<<union_matr[i][j]<<" "; }
//удаление из динамической памяти матрицы смежности
//объединенного графа
for(int i=0; i<N;i++) delete[] union_matr[i]; delete[] union_matr; }
В этой функции-операции создается в динамической памяти двумер­ный массив с указателем union_matr для матрицы смежности объединенно­го графа. Построение матрицы смежности объединенного графа заключает­ся в просмотре элементов двумерных массивов двух объектов одного и то­го же класса My_Class. Один массив с указателем Matr соответствует объекту, который будет расположен первым в записи перегруженной опе­рации (||). Элементы второго массива будут видны в функции-операции за счет аргумента этой функции – указателя на объект класса My_Class. Этому аргументу будет присвоен адрес объекта, который будет расположен вторым в записи перегруженной операции (||).
Поскольку указатель Matr является личным данным класса Graph, то доступ к нему возможен только с помощью функций этого класса. По­этому необходимо создать дополнительно функцию, которая возвращает значение элемента массива с указателем Matr. Эта функция должна иметь два аргумента, соответствующих индексам элементов массива. Назовем эту функцию return_ij(). Функция простая, поэтому определим ее в теле класса My_Class:
class My_Class : public Graph { public: void operator*(); //ввод номеров двух вершин
int operator!(); //проверка смежности двух //вершин
6.8. Бинарная функция-операция для объединения двух графов
59
My_Class(int a):Graph(a){} void operator++(); void operator>(int);
void operator||(My_Class *);
int return_ij(int i,int j){return Matr[i][j];}
};
Добавьте в главную функцию операторы для создания второго объ-
екта класса My_Class:
My_Class * graph_1 = new My_Class(number);
для ввода матрицы смежности второго графа:
+(*graph_1);
а также опреатор вывода на экран матрицы смежности объединения двух графов:
(*graph)||graph_1;
Обратите внимание, что первый операнд в бинарной операции (||)
должен быть обязательно объект класса, а не указатель. Это связано с пра­вилом использования перегрузки операций для объектов классов, по кото­рому прегрузка операций применяется только для объектов классов. По­этому для указателя graph на объект, соответствующий первому графу, применена операция взятия содержимого по адресу (*). Второй операнд – указатель на объект класса, соответствующий второму графу, так как при создании функции-операции operator||() выбран в качестве аргумента указатель на объект класса My_Class. Окончательно главная функция теперь будет такой:
int main() { int number; cout <<" Input number of Graph Tops: "; cin>>number;
6. Задачи на графах и перегрузка операций
60
My_Class * graph = new My_Class(number); +(*graph); // ввод матрицы смежности первого графа
-(*graph); // вывод матрицы смежности графа *(*graph); //ввод номеров двух вершин ++(*graph); graph->Graph::operator++(); *(*graph); //ввод номеров двух вершин cout<< " Tops "; if( !(*graph)) cout<<" Adjacent"; else cout<< " NO Adjacent";
//-- вершины смежные с заданной вершиной ------
cout<<endl<<" Input number of top: "; int x1; cin>>x1; (*graph)>x1;
//создание второго объекта
My_Class * graph_1 = new My_Class(number);
// ввод матрицы смежности второго графа
+(*graph_1);
//вывод на экран матрицы смежности объединения двух //графов
(*graph)||graph_1;
delete graph; getch(); return 0; }
Полный текст программы приведен в прил. 5.
6.9. Пример выполнения программы для бинарных функций-операций
Для графов, представленных на рис. 12 и рис. 14, матрицы смежности показаны соответственно на рис. 13 и рис. 15. На рис. 16 показан граф, по­лученный в результате объединения этих графов. Матрица смежности по­казана на рис. 17.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]