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

Министерство Образования и Исследований Республики Молдова

Технический Университет Молдовы Департамент Физики

Отчет
по лабораторной работе Nr.1.
по Дискретной математике

Тема: Хранение графов в памяти ЭВМ.

Выполнил ст.гр. TI-239 Socot Andrei

Кишинев – 2023
Цель работы:
1. Освоение и изучение способов задания графов: матрица
инцидентности, матрица смежности, список смежности.
2. Разработка процедур преобразования видов хранения графов с
выдачей результатов на дисплей.
Задание
1. Разработать процедуры ввода графа в виде матрицы
инцидентности, матрицы смежности и списка смежности с
возможностью корректировки введенных данных.
2.Разработать процедуры преобразования различных форм
хранения графа:
-- из матрицы смежности в список смежности и обратно;
-- из матрицы инцидентности в список смежности и обратно;
3. Используя указанные выше процедуры, получить
программу, выполняющую следующие функции:
--ввод графа в любой из трех форм представления (по требованию
пользователя);
--хранение введенного графа в памяти ЭВМ в виде списка
смежности;
-- вывод информации о графе в любом из трех видов (также по
требованию пользователя) на дисплей;

Код программы:
#include <stdio.h>
#include <stdlib.h>

// Функция для выделения памяти под список смежности


int** allocateAdjacencyList(int vershina) {
int **spisoc_smejnosti = (int **)malloc(vershina * sizeof(int *));
for (int i = 0; i < vershina; ++i) {
spisoc_smejnosti[i] = (int *)malloc(vershina * sizeof(int));
for (int j = 0; j < vershina; ++j) {
spisoc_smejnosti[i][j] = 0; // Инициализация нулями
}
}
return spisoc_smejnosti;
}

// Функция для выделения памяти под матрицу инцидентности


int** allocateIncidenceMatrix(int numEdges, int vershina) {
int **num = (int **)malloc(numEdges * sizeof(int *));
for (int i = 0; i < numEdges; ++i) {
num[i] = (int *)malloc(vershina * sizeof(int));
for (int j = 0; j < vershina; ++j) {
num[i][j] = 0; // Инициализация нулями
}
}
return num;
}

// Функция для выделения памяти под одномерный динамический массив


int* allocateDynamicArray(int numEdges) {
return (int*)malloc(numEdges * sizeof(int));
}
// Функция для освобождения памяти списка смежности
void freeAdjacencyList(int **spisoc_smejnosti, int vershina) {
for (int i = 0; i < vershina; ++i) {
free(spisoc_smejnosti[i]);
}
free(spisoc_smejnosti);
}

// Функция для освобождения памяти матрицы смежности


void freeAdjacencyMatrix(int **mat_smejnosti, int vershina) {
for (int i = 0; i < vershina; ++i) {
free(mat_smejnosti[i]);
}
free(mat_smejnosti);
}
// Функция для освобождения памяти одномерного динамического массива
void freeDynamicArray(int *dynamicArray) {
free(dynamicArray);
}

void printAdjacencyMatrix(int **spisoc_smejnosti,int **mat_smejnosti, int


vershina) {
printf("\nМатрица смежности:\n");
for (int i = 0; i < vershina; ++i) {
for (int j = 0; j < vershina; ++j) {
if (spisoc_smejnosti[i][j] == 1 || spisoc_smejnosti[i][j] == 2 )
{
mat_smejnosti[i][j]=1;
}
printf("%d ",mat_smejnosti[i][j]);

}
printf("\n");
}
}
void printAdjacencyList_from_Matrix(int **spisoc_smejnosti, int vershina){
printf("\nСписок смежности:\n");
for (int i = 0; i < vershina; ++i) {
printf("Вершина %d: ", i + 1);
for (int j = 0; j < vershina; ++j) {
if (spisoc_smejnosti[i][j] == 1|| spisoc_smejnosti[i][j]==2 ) {
printf("%d ", j + 1);
}
}
printf("0\n");
}
}
int** AdjacencyList_makeing(int **spisoc_smejnosti, int numEdges) {
int start, end;

for (int k = 0; k < numEdges; ++k) {


printf("Введите начальную и конечную вершины для ребра %d: ", k + 1);
scanf("%d %d", &start, &end);
spisoc_smejnosti[start - 1][end - 1] = 1;
if (start - 1 == end - 1) {
spisoc_smejnosti[start - 1][end - 1] = 2;
}
}

return spisoc_smejnosti;
}
void printIncidenceMatrix(int **num, int numEdges, int vershina) {
printf("\nМатрица инцидентности:\n");
for (int i = 0; i < numEdges; ++i) {
for (int j = 0; j < vershina; ++j) {
printf("%d ", num[i][j]);
}
printf("\n");
}
}
int getUserChoice() {
int choice;

printf("Выберите действие:\n");
printf("1. Переход из списка смежности в матрицу смежности\n");
printf("2. Переход из матрицы смежности в список смежности\n");

printf("Ваш выбор: ");


scanf("%d", &choice);
return choice;
}

void processStep1(int vershina,int**spisoc_smejnostii) {


int** spisoc_smejnosti = spisoc_smejnostii;
int** mat_smejnosti = allocateAdjacencyList( vershina);

printAdjacencyMatrix(spisoc_smejnosti, mat_smejnosti, vershina);


freeAdjacencyMatrix(mat_smejnosti, vershina);
}

void processThirdStep(int vershina, int**spisoc_smejnostii) {


int** spisoc_smejnosti = spisoc_smejnostii;
printAdjacencyList_from_Matrix(spisoc_smejnosti, vershina);

}
void processDynamicArrayAndPrintIncidenceMatrix(int **spisoc_smejnosti, int
numEdges, int vershina) {
int **num = allocateIncidenceMatrix(numEdges, vershina);
int *dynamicArray = allocateDynamicArray(numEdges);
int k = 0;
int **spisoc_smejnostii = spisoc_smejnosti;
for (int i = 0; i < vershina; ++i) {
for (int j = 0; j < vershina; ++j) {
if (spisoc_smejnostii[i][j] == 1 || spisoc_smejnostii[i][j] == 2)
{
dynamicArray[k] = (i+1) * 10 + (j);
k++;

}
}
}
for (int k = 0; k < numEdges; ++k) {
int i = (dynamicArray[k] / 10)-1;
int j = dynamicArray[k] % 10;
if (spisoc_smejnostii[i][j] == 2) {
num[k][i] = 2;

} else {
num[k][i] = -1;
num[k][j] = 1;
}
}
printf("\nМатрица инцидентности:\n");
for (int i = 0; i < numEdges; ++i) {
for (int j = 0; j < vershina; ++j) {
printf("%d ", num[i][j]);
}
printf("\n");
}

freeDynamicArray(dynamicArray);
}
int** processsDynamicArrayAndReturnIncidenceMatrix(int **spisoc_smejnosti, int
numEdges, int vershina) {
int **num = allocateIncidenceMatrix(numEdges, vershina);
int *dynamicArray = allocateDynamicArray(numEdges);
int k = 0;
int **spisoc_smejnostii = spisoc_smejnosti;

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


for (int j = 0; j < vershina; ++j) {
if (spisoc_smejnostii[i][j] == 1 || spisoc_smejnostii[i][j] == 2)
{
dynamicArray[k] = (i+1) * 10 + (j);
k++;
}
}
}

for (int k = 0; k < numEdges; ++k) {


int i = (dynamicArray[k] / 10) - 1;
int j = dynamicArray[k] % 10;

if (spisoc_smejnostii[i][j] == 2) {
num[k][i] = 2;
} else {
num[k][i] = -1;
num[k][j] = 1;
}
}

freeDynamicArray(dynamicArray);

return num;
}
void incidenceMatrixToAdjacencyList(int **num, int vershina,int numEdges) {
int intident_spisoc[vershina][vershina];
for (int i = 0; i < vershina; ++i) {
for (int j = 0; j < vershina; ++j) {
intident_spisoc[i][j] = 0;
}
}

int d = 0;
for (int i = 0; i < numEdges; ++i) {
for (int j = 0; j < vershina; ++j) {
if (num[i][j] == -1) {
d = j;
for (int k = 0; k < vershina; ++k) {
if (num[i][k] == 1) {
intident_spisoc[d][k] = 1;
}
}
} else if (num[i][j] == 2) {
intident_spisoc[j][j] = 1;
}
}
}

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


printf("Вершина %d: ", i + 1);
for (int j = 0; j < vershina; ++j) {
if (intident_spisoc[i][j] == 1) {
printf("%d ", j + 1);
}
}
printf("0\n");
}
}
void freeIncidenceMatrix(int **num, int numEdges) {
for (int i = 0; i < numEdges; ++i) {
free(num[i]);
}
free(num);
}

int main() {
system("chcp 65001");
int vershina, choice, numEdges, da;
choice = 1;
while (choice != 0) {
printf("Введите количество вершин в графе: ");
scanf("%d", &vershina);
printf("Введите количество рёбер в графе: ");
scanf("%d", &numEdges);
choice = getUserChoice();
int a;
int **spisoc_smejnostii;
spisoc_smejnostii = allocateAdjacencyList(vershina);
spisoc_smejnostii = AdjacencyList_makeing(spisoc_smejnostii,
numEdges);
switch (choice) {
case 1:
processStep1(vershina, spisoc_smejnostii);
printf("Матрица смежности->список смежности-----> 2\n");
scanf("%d", &choice);
if (choice == 2) {
processThirdStep( vershina, spisoc_smejnostii);
}
printf("Введите 1 если хотите изменить ввод ");
scanf("%d", &a);
if (a == 1) {
freeAdjacencyList(spisoc_smejnostii, vershina);
printf("Введите количество вершин в графе: ");
scanf("%d", &vershina);
printf("Введите количество рёбер в графе: ");
scanf("%d", &numEdges);
printf("Список смежности->матрица смежности-----> 1\n ");
scanf("%d", &a);
if (a==1)
{
spisoc_smejnostii = allocateAdjacencyList(vershina);
spisoc_smejnostii =
AdjacencyList_makeing(spisoc_smejnostii, numEdges);
processStep1(vershina, spisoc_smejnostii);
}
printf("Матрица смежности->список смежности-----> 2 \n");
scanf("%d", &choice);
if (choice == 2) {
processThirdStep( vershina, spisoc_smejnostii);
}
}
printf("Для завершения программы нажмите 0\n");
scanf("%d", &choice);
if (choice == 0) {
break;
}
printf("Cписок смежности->матрица инцидентности\n");
case 2:
processDynamicArrayAndPrintIncidenceMatrix(spisoc_smejnostii,
numEdges, vershina);
int** incidenceMatrix =
processsDynamicArrayAndReturnIncidenceMatrix(spisoc_smejnostii, numEdges,
vershina);
printf("Матрица инцидентности->список смежности-----> 4\n");
scanf("%d", &choice);
if (choice == 4) {
incidenceMatrixToAdjacencyList(incidenceMatrix, vershina,
numEdges);
//МАТРИЦА ИНЦИДЕНТНОСТИ СПИСОК СМЕЖНОСТИ
}
printf("Введите 1 если хотите изменить ввод\n ");
scanf("%d", &a);
if (a == 1) {
freeAdjacencyList(spisoc_smejnostii, vershina);
freeIncidenceMatrix(incidenceMatrix,numEdges);
printf("Введите количество вершин в графе: ");
scanf("%d", &vershina);
printf("Введите количество рёбер в графе: ");
scanf("%d", &numEdges);
spisoc_smejnostii = allocateAdjacencyList(vershina);
spisoc_smejnostii =
AdjacencyList_makeing(spisoc_smejnostii, numEdges);
printf("Список смежности->матрица инцидентности-----> 1\
n");
scanf("%d", &a);
if (a==1)
{

processDynamicArrayAndPrintIncidenceMatrix(spisoc_smejnostii, numEdges,
vershina);
}
printf("Матрица инцидентности->список смежности-----> 2\
n");
scanf("%d", &choice);
if (choice == 2) {
int** incidenceMatrix =
processsDynamicArrayAndReturnIncidenceMatrix(spisoc_smejnostii, numEdges,
vershina);
incidenceMatrixToAdjacencyList(incidenceMatrix,
vershina, numEdges);

freeAdjacencyList(spisoc_smejnostii, vershina);
freeIncidenceMatrix(incidenceMatrix,numEdges);
}
}
break;
}
printf("Для завершения программы нажмите 0\n");
scanf("%d", &choice);
}
}

///Пример ввода:

Введите количество вершин в графе:6

Введите количество рёбер в графе:9

Выберите действие:

1. Переход из списка смежности в матрицу смежности

2. Переход из матрицы смежности в список смежности

Ваш выбор:1

Введите начальную и конечную вершины для ребра 1:1 2

12

Введите начальную и конечную вершины для ребра 2:2 1

21

Введите начальную и конечную вершины для ребра 3:3 3

33

Введите начальную и конечную вершины для ребра 4:3 4

34

Введите начальную и конечную вершины для ребра 5:4 5

45

Введите начальную и конечную вершины для ребра 6:5 5

55
Введите начальную и конечную вершины для ребра 7:5 1

51

Введите начальную и конечную вершины для ребра 8:5 2

52

Введите начальную и конечную вершины для ребра 9:5 3

53

Матрица смежности->список смежности

Cписок смежности->матрица инцидентности


Матрица инцидентности->список смежности
Основные способы задания графов:

Матрица смежности: Представляет собой квадратную матрицу, где строки и столбцы


соответствуют вершинам графа, а на пересечении i-й строки и j-го столбца указывается,
есть ли ребро между вершинами i и j.
Список смежности: Представляет собой список, где каждой вершине соответствует
список смежных с ней вершин.
Матрица инцидентности: Представляет собой матрицу, где строки соответствуют
ребрам, а столбцы вершинам. В ячейке (i, j) указывается, инцидентен ли i-й ребро j-й
вершине.

Описание недостатков и преимуществ каждого способа:

Матрица смежности:
Преимущества: Простота проверки смежности вершин, эффективен для плотных графов.
Недостатки: Требует O(V^2) памяти, что неэффективно для разреженных графов.
Список смежности:
Преимущества: Экономичен для разреженных графов, занимает O(V + E) памяти, где V -
количество вершин, E - количество ребер.
Недостатки: Большее время доступа к смежным вершинам.
Матрица инцидентности:
Преимущества: Прост в реализации.
Недостатки: Требует O(V * E) памяти, что неэффективно.

Типы переменных для реализации:

Матрица смежности: Двумерный массив или массив массивов (в языке C), булевы
значения для отметки смежности.
Список смежности: Динамический массив или связанный список, где каждый элемент
содержит информацию о вершине и указатель на следующий элемент
Матрица инцидентности: Двумерный массив или массив массивов (в языке C), булевы
значения для отметки инцидентности.

Самый экономичный способ:


Список смежности является самым экономичным способом для разреженных графов.
Память занимается пропорционально количеству вершин и ребер, что делает его
эффективным в использовании памяти.

Вывод:
В ходе разработки этой программы, я приобрел навыки работы с различными представлениями
графов и их преобразованием. Ключевые моменты в моем опыте включают:

1.Динамическая память: Овладение работой с динамической памятью позволило мне эффективно


управлять ресурсами, избегая утечек памяти.

2.Использование функций: Я структурировал код, разбив его на функции, что сделало программу
более читаемой и легкой для обслуживания.

3.Работа с представлениями графов: Моя программа позволяет пользователям вводить графы в


виде списков смежности, а затем производить переходы между матрицей смежности и матрицей
инцидентности.

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