Вы находитесь на странице: 1из 8

MINISTERUL EDUCAȚIEI ȘI CERCETĂRII AL

REPUBLICII MOLDOVA

Universitatea Tehnică a Moldovei


Facultatea Calculatoare, Informatică și Microelectronică
Departamentul Inginerie Software și Automatică

RAPORT
Lucrare de laborator nr. 1
la cursul „Matematica discretă”
Tema: Хранение графов в памяти ЭВМ.

A efectuat : St. gr. TI-228, Dudnic Elizaveta


A verificat: Asis.univ. Gaidarji Alina

Chișinău 2023
Введение:
Тема: Хранение графов в памяти ЭВМ.
Цель работы:
1. Освоение и изучение способов задания графов: матрица инцидентности,
матрица смежности, список смежности.
2. Разработка процедур преобразования видов хранения графов с выдачей
результатов на дисплей.

Способы задания графов


Существует три основных способа дискретного задания графа:
1). Матрица инцидентности;
2). Матрица смежности;
3). Список смежности ( инцидентности );

Задание
1. Разработать процедуры ввода графа в виде матрицы
инцидентности, матрицы смежности и списка смежности с возможностью
корректировки введённых данных.
2. Разработать процедуры преобразования различных форм
хранения графа:

--из матрицы смежности в список смежности и обратно;

--из матрицы инцидентности в список смежности и обратно;


3. Используя указанные выше процедуры, получить программу,
выполняющую следующие функции:
--ввод графа в любой из трех форм представления (по требованию
пользователя) ;

--хранение введённого графа в памяти ЭВМ в виде списка


смежности;

-- вывод информации о графе в любом из трех видов ( также по


требованию пользователя ) на дисплей;

Теория:

Матрица смежности - это вид представления графа в виде матрицы, когда пересечение
столбцов и строк задаёт дуги. Используя матрицу смежности, можно задать вес дуг и
ориентацию. Каждая строка и столбец матрицы соответствуют вершинам, номер
строки соответствует вершине, из которой выходит дуга, а номер столбца - в какую
входит дуга.

Матрица инцидентности имеет вид представления графа в виде матрицы, в которой


каждый столбец задаёт отдельную дугу. Строки матрицы при этом задают вершины.
Положительное число в столбце задаёт вершину, из которой выходит дуга, а
отрицательное - в которую входит. Если оба числа положительные, то дуга
неориентированная.
Список смежности — один из способов представления графа в виде коллекции
списков вершин. Каждой вершине графа соответствует список, состоящий из «соседей»
этой вершины.

Выполнение(LISTING):

#include <iostream>
#include <vector>
using namespace std;
void MS_MI(int **ms, int n, int m, int check);
void SS_MS(vector<int> *ss, int n, int m, int check) {
int **ms = new int *[n];
for (int i = 0; i < n; i++) { ms[i] = new int[n]; }
for (int i = 0; i < n; i++) {
for (auto it = ss[i].begin(); it != ss[i].end(); it++) {
if (i == ((*it) - 1)) { ms[i][*it - 1] = 1; }
else { ms[i][*it - 1] = 1; }
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << ms[i][j] << ' ';
}
cout << "\n";
}
cout << "\n";
check++;
if (check < 3) { MS_MI(ms, n, m, check); }
}
void MI_SS(int **mi, int n, int m, int check){
vector<int> ss[n];
int k=-1;
int l=-1;
int j= 0;
for(int i=0; i<m; i++){
for(j=0; j<n; j++){
if(mi[i][j]==-1){k=j;}
else if(mi[i][j]==1){l=j;}
else if(mi[i][j]==2){
l=j;
k=j;
}
}
}
if(k>-1){
ss[k].push_back(l+1);
k=-1;
j=-1;
}
cout << "\n";
for(int i=0; i<n; i++){
cout << "index " << i+1 << ": ";
for(auto it = ss[i].begin(); it != ss[i].end(); it++){
cout << *it << ' ';
}
cout << "\n";
}
cout << "\n";
check++;
if(check<3){SS_MS(ss, n, m, check);}
}
void MS_MI(int **ms, int n, int m, int check){
int **mi = new int*[m];
for(int i=0; i<m; i++){ mi[i] = new int[n]; }

int k=0;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(ms[i][j]==1 && i!=j) {
mi[k][i] = -1;
mi[k][j] = 1;
k++;
}
if(ms[i][j]==2 || (ms[i][j]==1 && i==j)){
mi[k][j]=2;
k++;
}
}
} cout << "\n";
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
cout << mi[i][j] << ' ';
}
cout << "\n";
}
check++;
if(check<3){MI_SS(mi, n, m, check);}
}
void intnumMS(){
int n, m;
cout << "Enter number of vertices(kolichestvo VERSHIN): "; cin >> n; cout << "\n";
cout << "Enter number of ribs(kolichestvo REBER): "; cin >> m; cout << "\n";
int **ms = new int*[n];
for(int i=0; i<n; i++){ ms[i] = new int[n];}
cout << "Please enter data: ";
for(int i=0; i<n;i++){
for(int j=0; j<n; j++){
cin >> ms[i][j];
}
}
for(int i=0; i<n;i++){
cout << "\n";
for(int j=0; j<n; j++){
cout << ms[i][j] << ' ';
}
}
cout << "\n";
int ch = 1;
MS_MI(ms, n, m, ch);
}
void intnumMI(){
int n, m;
cout << "Enter number of vertices(kolichestvo VERSHIN): "; cin >> n; cout << "\n";
cout << "Enter number of ribs(kolichestvo REBER): "; cin >> m; cout << "\n";
int **mi = new int*[m];
for(int i=0; i<m; i++){ mi[i] = new int[n]; }

cout << "Please enter data: ";


for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
cin >> mi[i][j];
}
}
for(int i=0; i<m; i++){
cout << "\n";
for(int j=0; j<n; j++){
cout << mi[i][j] << ' ';
}
}
cout << "\n";
int check = 1;
MI_SS(mi, n, m, check);
}
void intnumSS(){
int n, m, s;
cout << "Enter number of vertices(kolichestvo VERSHIN): "; cin >> n; cout << "\n";
cout << "Enter number of ribs(kolichestvo REBER): "; cin >> m; cout << "\n";
vector<int> ss[n];

for(int i=0; i<n; i++){


for(int j=0; j<n; j++){
cin >> s;
if(s!=0){ ss[i].push_back(s); }
else break;
}
}
cout << "\n";
for(int i=0; i<n; i++){
cout << "index " << i+1 << ": ";
for(auto it = ss[i].begin(); it != ss[i].end(); it++){
cout << *it << ' ';
}
cout << "\n";
}
cout << "\n";
int ch = 1;
SS_MS(ss, n, m, ch);
}

int main(){
int intnum;
cout << "Press 1, if you need to input Adjacency Matrix(MATRICA SMEJNOSTI) : "
<< "\n";
cout << "Press 2, if you need to input Incident Matrix(MATRICA INCIDENTNOSTI): "
<< "\n";
cout << "Press 3, if you need to input Adjacency List(SPISOK SMEJNOSTI): " << "\n";
cin >> intnum;
switch(intnum){
case 1: intnumMS();
case 2: intnumMI();
case 3: intnumSS();
}
}

Контрольные вопросы

1. Какие существуют основные способы задания графов ?


2. Опишите каждый из способов задания, его недостатки и
преимущества.
3. Какие типы переменных используются для реализации каждого из
способов представления графа ?
4. Какой способ представления графов самый экономичный и почему
? Расскажите, как реализуется этот способ хранения на языке Pascal и в как
при этом граф хранится в памяти ЭВМ.

1) Способы задания графов


1. графический;

2. с помощью перечисления рёбер;

3. с помощью матрицы смежности;

4. с помощью матрицы инцидентности.


2) 1. С графическим способом, при котором вершины графа изображаются
точками на плоскости или в пространстве, а ребра – непрерывными кривыми,
соединяющими соответствующие точки, мы уже фактически познакомились.
2. При помощи матрицы смежности. Матрицей смежности ориентированного
помеченного графа с вершинами называется матрица А = [a,-,], i,j = 1, ..., п,
строки которой соответствуют вершинам, а столбцы — рёбрам, в которой:
Ujj = 1, если существует ребро (х), х,);
(ijj = 0, если вершины х,, Xj не связаны ребром.
3. Матрица инциденций – это прямоугольная матрица, число строк которой
равно числу вершин, а число столбцов – числу дуг (рёбер) графа. Элементы
этой матрицы определяются следующим образом:

4. Список смежности представляет собой список из n строк, ( n -


количество вершин), где в i - ой строке записываются номера вершин,
смежных с вершиной под номером i. Как мы видим, этот список тем
больше, чем больше связей между вершинами графа.

Преимущества матрицы смежности:


Сложность проверки наличия ребра между двумя вершинами: O(1)
Недостатки матрицы смежности:
Занимает N2 памяти, что неприемлемо для достаточно больших графов.
Сложность перебора всех вершин, смежных с данной: O(N)
Преимущества списка смежности:
Использует O(M) памяти, что оптимально.
Позволяет быстро перебирать соседей вершины.
Позволяет за O(logN) проверять наличие ребра и удалять его (при
использовании std::set).
Недостатки списка смежности:
При работе с насыщенными графами (количество рёбер близко к N2) скорости
O(logN) может не хватать (единственный повод использовать матрицу
смежности).
Для взвешенных графов приходится хранить vector<pair<int, int>>, что
усложняет код.
3) Во всех случая хранения графов применяются целочисленные переменные.
Можно использовать int. Небольшим отличием является потребность
матрицы смежности только в 0 и 1, матрицы инцидентности только в -1 , 0 и
1, а список уже использует числа равные количеству вершин графа.
4) Самым экономичным способом хранения графа в памяти ЭВМ является его
хранение путём списка смежности. В С++ список смежности можно
реализовать путём нескольких вариантов, например, самый банальный, это
через двумерный массив, так же можно через вектор векторов, через массив
структур, но самым рациональным все же является хранение графа через
список смежности при помощи односвязного списка. Односвязный список это
своеобразная структура данных, которая хранит в себе значение и указатель
на другое значение. То есть мы получаем доступ к одному через другое. Это
очень гибкая структура данных, которая позволяет нам делать различные
манипуляции с хранением.

Вывод:
Выполняя эту лабораторную работу я ознакомилась с представлением графов
на языке программирования С++. Научилась их вводить в разных форматах:
матрица смежности, матрица инцидентности, список смежности, так же
выводить их на экран. Обрела навык написания функции для перевода графов
из одного формата в другой, по выбору пользователя. Для выполнения
данной лабораторной работы было необходимо ознакомиться с графами и
синтаксисом, использованным в дискретной математике.

Вам также может понравиться