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

Universitatea Techinca a Moldovei

Departamentul Ingenerie Software Automatice

Отчёт
О выполнении лабораторной работы №4
По Дискретной Математике.
Тема: Использование структур данных для поиска на
деревьях и графах. Алгоритм поиска Форда.

Выполнил: Шокот Андрей


Проверила: Т. Тихолаз

Кишинёв, 2024.
Цель работы: Изучение алгоритмов поиска минимального пути в
графе. Разработка программы, реализующей данные алгоритмы
поиска минимального пути в взвешенном графе.

Поиск минимального пути по алгоритму Форда

Алгоритм Форда позволяет от какой-либо исходной вершины Xi


определить минимальный путь до произвольной вершины Xj графа G.
Алгоритм Форда состоит из следующих шагов:
1) Каждой вершине Xi графа G ставятся в соответствие
максимально возможные для данной задачи числа Hi;
2) На втором шаге вычисляются разности Hj-Hi для каждой
вершины Xi, где Hj - вес вершины, в которую ведет дуга (Xi,Xj). Здесь
возможны три случая: Hj - Hi < Lij, Hj-
Hi=Lij, Hj-Hi>Lij, где Lij - вес дуги, ведущей из вершины Xi в вершину Xj.
Случай, когда Hj-Hi>Lij позволяет нам уменьшить расстояние
между вершинами Xi и Xj благодаря следующим преобразованиям:
Hj-Hi>Lij, Hj > Lij + Hi, отсюда принимаем: Hj=Hi+Lij.
Второй шаг выполняется до тех пор, пока еще существуют пары
(i,j), для которых выполняется неравенство Hj-Hi>Lij.
По окончанию второго этапа метки вершин позволяют нам
определить значение минимального пути из исходной в конечную
вершину;
3) На третьем этапе происходит определение минимального пути
при помощи обратного хода от конечной вершины к начальной,
причем для вершины Xj предшествующей будет вершина Xi, если для
этой пары выполняется Hj-Hi=Lij. Если существует несколько таких
пар, то выбирается любая из них.
Вывод: На этой лабораторной работе, я закрепил алгоритм поиска минимального пути в
графе. После чего, разработал программу, реализующую данные алгоритмы поиска
минимального пути в взвешенном графе. Именно такие алгоритмы используются при
решении задач.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define INFINITY 10000


#define NEGATIVE_INFINITY -10000

typedef struct Node


{
int vertex;
int link;
int weight;
struct Node *next;
} Node;
typedef struct Graph
{
int vertices;
int edges;
Node **adjacencyList;
} Graph;

typedef struct Path


{
int *nodes;
int length;
int distance;
struct Path *next;
} Path;

Graph *createGraph(int vertices, int edges)


{
Graph *graph = malloc(sizeof(Graph));
graph->vertices = vertices;
graph->edges = edges;

graph->adjacencyList = malloc(vertices * sizeof(Node *));


for (int i = 0; i < vertices; i++)
{
graph->adjacencyList[i] = NULL;
}

return graph;
}

void addEdge(Graph *graph, int start, int end, int weight)


{
Node *newNode = malloc(sizeof(Node));
newNode->vertex = end;
newNode->link = start;
newNode->weight = weight;
newNode->next = NULL;

if (graph->adjacencyList[start] == NULL)
{
graph->adjacencyList[start] = newNode;
}
else
{
Node *current = graph->adjacencyList[start];
while (current->next != NULL)
{
current = current->next;
}
current->next = newNode;
}
}
void displayGraph(Graph *graph)
{
printf("\n");
for (int i = 0; i < graph->vertices; i++)
{
Node *current = graph->adjacencyList[i];
printf("%d:", i + 1);
while (current != NULL)
{
printf(" %d (%d) [%d]", current->vertex + 1, current->link + 1,
current->weight);
if (current->next != NULL)
{
printf(", ");
}
current = current->next;
}
printf("\n");
}
}

void addPath(Path **paths, int *nodes, int length, int distance)


{
Path *newPath = malloc(sizeof(Path));
newPath->nodes = malloc(length * sizeof(int));
for (int i = 0; i < length; i++)
{
newPath->nodes[i] = nodes[i];
}
newPath->length = length;
newPath->distance = distance;
newPath->next = *paths;
*paths = newPath;
}

void freePaths(Path *paths)


{
Path *current = paths;
while (current != NULL)
{
Path *temp = current;
current = current->next;
free(temp->nodes);
free(temp);
}
}

void printPath(int *nodes, int length)


{
for (int i = 0; i < length; i++)
{
printf("%d ", nodes[i] + 1);
}
}

void printPaths(Path *paths)


{
Path *current = paths;
while (current != NULL)
{
printPath(current->nodes, current->length);
printf("(distance:%d)\n", current->distance);
current = current->next;
}
}

void findMinPaths(Graph *graph, int start, int dest, int *visited, int *nodes,
int pathLength, int pathDistance, int *minDistance, Path **paths)
{
visited[start] = true;
nodes[pathLength] = start;
pathLength++;

if (start == dest)
{
if (pathDistance < *minDistance)
{
*minDistance = pathDistance;
freePaths(*paths);
*paths = NULL;
}
if (pathDistance == *minDistance)
{
addPath(paths, nodes, pathLength, pathDistance);
}
}
else
{
Node *current = graph->adjacencyList[start];
while (current != NULL)
{
if (!visited[current->vertex])
{
findMinPaths(graph, current->vertex, dest, visited, nodes,
pathLength, pathDistance + current->weight, minDistance, paths);
}
current = current->next;
}
}
visited[start] = false;
}

void findMaxPaths(Graph *graph, int start, int dest, int *visited, int *nodes,
int pathLength, int pathDistance, int *maxDistance, Path **paths)
{
visited[start] = true;
nodes[pathLength] = start;
pathLength++;

if (start == dest)
{
if (pathDistance > *maxDistance)
{
freePaths(*paths);
*paths = NULL;
*maxDistance = pathDistance;
}
if (pathDistance == *maxDistance)
{
addPath(paths, nodes, pathLength, pathDistance);
}
}
else
{
Node *current = graph->adjacencyList[start];
while (current != NULL)
{
if (!visited[current->vertex])
{
findMaxPaths(graph, current->vertex, dest, visited, nodes,
pathLength, pathDistance + current->weight, maxDistance, paths);
}
current = current->next;
}
}

visited[start] = false;
}

void findMinPathsWithFord(Graph *graph, int start, int dest)


{
int *visited = malloc(graph->vertices * sizeof(int));
int *nodes = malloc(graph->vertices * sizeof(int));
int pathLength = 0;
int pathDistance = 0;
int minDistance = INFINITY;
Path *paths = NULL;

for (int i = 0; i < graph->vertices; i++)


{
visited[i] = false;
}

findMinPaths(graph, start, dest, visited, nodes, pathLength, pathDistance,


&minDistance, &paths);
printPaths(paths);

free(visited);
free(nodes);
freePaths(paths);
}

void findMaxPathsWithFord(Graph *graph, int start, int dest)


{
int *visited = malloc(graph->vertices * sizeof(int));
int *nodes = malloc(graph->vertices * sizeof(int));
int pathLength = 0;
int pathDistance = 0;
int maxDistance = NEGATIVE_INFINITY;
Path *paths = NULL;

for (int i = 0; i < graph->vertices; i++)


{
visited[i] = false;
}

findMaxPaths(graph, start, dest, visited, nodes, pathLength, pathDistance,


&maxDistance, &paths);
printPaths(paths);

free(visited);
free(nodes);
freePaths(paths);
}

int main()
{
printf("Enter number of vertices: ");
int vertices;
scanf("%d", &vertices);

printf("Enter number of edges: ");


int edges;
scanf("%d", &edges);

Graph *graph = createGraph(vertices, edges);

printf("Enter edges in the format from start to end point with the weight of
the link between them:\n");
for (int i = 0; i < edges; i++)
{
int start, end, weight;
scanf("%d %d %d", &start, &end, &weight);
addEdge(graph, start - 1, end - 1, weight);
}

printf("Enter start vertex for Ford's algorithm: ");


int startVertex;
scanf("%d", &startVertex);
startVertex--;

printf("Enter destination vertex for Ford's algorithm: ");


int destVertex;
scanf("%d", &destVertex);
destVertex--;

int option;
do
{
printf("\n");
printf("Choose an option:\n");
printf("1. Show min path.\n");
printf("2. Show max path.\n");
printf("3. Exit.\n");

scanf("%d", &option);

switch (option)
{
case 1:
findMinPathsWithFord(graph, startVertex, destVertex);
break;
case 2:
findMaxPathsWithFord(graph, startVertex, destVertex);
break;
case 3:
return 0;
default:
printf("Wrong option\n");
break;
}

} while (option != 3);

return 0;
}

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