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

Практика 6(СД)

.pdf
Скачиваний:
0
Добавлен:
08.10.2025
Размер:
472.54 Кб
Скачать

graph.Dijkstra(start); // запускаем алгоритм Дейкстры

}

}

// Класс Graph описывает граф через матрицу весов class Graph

{

private int[,] matrix; // матрица весов: matrix[i,j] — вес ребра из i в j (0 =

ребро отсутствует)

private int verticesCount; // число вершин графа

public Graph(int n) // конструктор класса Graph

{

verticesCount = n; matrix = new int[n, n];

// Инициализация матрицы нулями — пока ребер нет for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++) matrix[i, j] = 0;

}

// Добавляет ориентированное ребро с весом

11

public void AddEdge(int from, int to, int weight = 1) // from — индекс начальной вершины ребра. to — индекс конечной вершины ребра. weight —

вес ребра

{

matrix [from, to] = weight;

}

// Генерирует случайный граф с заданным числом ребер и весами

public void RandomGraph(int maxWeight = 10)

{

Random rand = new Random();

Console.WriteLine("Введите количество ребер для случайного графа:");

int m = int.Parse(Console.ReadLine());

int added = 0;

while (added < m) // заполняем матрицу

{

int from = rand.Next(verticesCount);

int to = rand.Next(verticesCount);

if (from == to) continue; // Исключаем петли — ребра из вершины в саму себя

int weight = rand.Next(1, maxWeight + 1); // вес ребра от 1 до maxWeight

(10)

12

AddEdge(from, to, weight); added++;

}

}

// Выводит матрицу весов с подписями public void Display()

{

Console.Write("\t");

for (int j = 0; j < verticesCount; j++) Console.Write((char)('A' + j) + "\t"); // подписи столбцов

Console.WriteLine();

for (int i = 0; i < verticesCount; i++)

{

Console.Write((char)('A' + i) + "\t"); // подписи строк for (int j = 0; j < verticesCount; j++)

Console.Write(matrix[i, j] + "\t"); // веса ребер

Console.WriteLine();

}

}

13

// Реализация алгоритма Дейкстры, ищет минимальные расстояния из start

во все остальные вершины public void Dijkstra(int start)

{

const int INF = int.MaxValue; // бесконечность для инициализации int[] dist = new int[verticesCount]; // массив расстояний от start

bool[] visited = new bool[verticesCount]; // пометки посещенных вершин int[] prev = new int[verticesCount]; // массив для восстановления пути

for (int i = 0; i < verticesCount; i++) // изначальная установка данных

{

dist[i] = INF; // расстояния изначально бесконечны visited[i] = false; // вершины не посещены

prev[i] = -1; // предшественник не известен

}

dist[start] = 0; // расстояние от себя до себя равно 0

// Основной цикл. Графы, рёбра, начальная вершина(выбирает пользователь)

for (int count = 0; count < verticesCount - 1; count++) // На каждом шаге мы расширяем область известных кратчайших путей, постепенно находя минимальное расстояние до новых вершин.

{

14

int u = MinDistance(dist, visited); // выбираем непосещённую вершину с минимальной дистанцией

if (u == -1) break; // если таких нет, останавливаемся visited[u] = true; // отмечаем вершину посещённой

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

u

for (int v = 0; v < verticesCount; v++)

{

if (!visited[v] && matrix[u, v] > 0 && dist[u] != INF && dist[u] + matrix[u, v] < dist[v])

{

dist[v] = dist[u] + matrix[u, v]; prev[v] = u; // запоминаем путь

}

}

} // на выходе массив расстояний и массив предшественников

// Вывод результатов: кратчайшие расстояния и пути

Console.WriteLine($"Кратчайшие пути из вершины {(char)('A' + start)}:");

for (int i = 0; i < verticesCount; i++)

{

15

if (i == start) continue; // путь из вершины в себя не выводим if (dist[i] == INF)

Console.WriteLine($"{(char)('A' + start)} -> {(char)('A' + i)}: пути

нет");

else

{

Console.Write($"{(char)('A' + start)} -> {(char)('A' + i)} : {dist[i]} -

длина пути. Маршрут пути: ");

PrintPath(prev, i); // показывает маршрут

Console.WriteLine();

}

}

}

// Метод для нахождения вершины с минимальным dist среди непосещённых

private int MinDistance(int[] dist, bool[] visited)

{

int min = int.MaxValue; int minIndex = -1;

for (int v = 0; v < verticesCount; v++) // перебирает вершины

{

16

if (!visited[v] && dist[v] <= min) // проверка посещаемости и меньше ли найденного минимума

{

min = dist[v];

minIndex = v;

}

}

return minIndex;

}

// Рекурсивный вывод пути от start к вершине j

private void PrintPath(int[] prev, int j)

{

if (prev[j] == -1) // если предшественник вершины j не определён (равен -

1), значит, мы достигли начальной вершины.

{

Console.Write((char)('A' + j));

return;

}

PrintPath(prev, prev[j]);

Console.Write(" -> " + (char)('A' + j)); // происходит последовательный вывод пути от начальной вершины до текущей вершины с индексом j.

}

17

}

18

Соседние файлы в предмете Структуры данных