Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практики(Вариант №7) / Практическая работа №6.odt
Скачиваний:
0
Добавлен:
23.02.2026
Размер:
306.36 Кб
Скачать

Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования

«ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ» (ТУСУР)

Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)

ГРАФЫ Отчет по практической работе №6 по дисциплине «Структуры данных»

Студент гр.

________

__.__.2025

Принял

Преподаватель

кафедры КИБЭВС

________ Д.Р. Уразаев

__.__.2025

Задание

Реализовать возможность работы с графом N узлов, M ребер. Выберете самостоятельно структуру. Обеспечьте следующие интерфейсные методы:

  • ввод графа (можно случайным образом,можно вводить с клавиатуры) НЕДОПУСТИМО работать только с конечным числом ребер и узлов. Приложение должно позволять вводить разные графы. 

  • вывод графа - матрица смежности или весов

Вариант 3. Задана система дорог. Определить кратчайшее расстояние из города А в город В, при этом путь не должен проходить через город С и D.  Восстановить путь. 

Оглавление

Задание 2

Введение 4

1 ХОД РАБОТЫ 5

Заключение 10

Приложение А 11

    Введение

Целью работы является реализация программы для работы с графами, представляющими систему дорог с переменным числом узлов и рёбер. Программа позволяет вводить графы случайным образом или с клавиатуры и выводить матрицу смежности или весов. Основное внимание уделяется нахождению города с максимальной суммой кратчайших расстояний до остальных городов.

    1 Ход работы

В работе реализуется ориентированный граф и матрица смежности.

Ориентированный граф — В ориентированном графе рёбра имеют направление, что означает, что если есть ребро от узла A к узлу B, то это не подразумевает наличие ребра от B к A.

Матрица смежности — это квадратная матрица, которая используется для представления графа. Если граф содержит N узлов, матрица будет размером NxN.

Graph – инициализирует граф с заданным количеством городов, проверяет, чтобы количество городов было больше нуля, создает матрицу смежности, устанавливая расстояние между городами на 0 для одного и того же города и на очень большое значение для всех остальных пар. (рис .1)

Р исунок 1 — Graph

AddEdgeдобавляет ребро между двумя городами с заданным весом, проверяет корректность индексов и положительность веса, устанавливает расстояние в матрице смежности для ориентированного графа (рис. 2)

Р исунок 2 — AddEdge

PrintAdjMatrix — выводит матрицу смежности на экран (рис. 3)

Рисунок 3 — PrintAdjMatrix

FloydWarshall – реализует алгоритм Флойда-Уоршелла для нахождения кратчайших расстояний между всеми парами городов, создаёт новую матрицу расстояний, копируя данные из матрицы смежности и обновляя значения, если обнаруживаются более короткие пути через промежуточные города (рис. 4)

Р исунок 4 — FloydWarshall

FindShortestPathWithAvoidance — предназначена для нахождения кратчайшего пути между двумя городами в ориентированном графе с исключением указанных городов из маршрута. (рис. 5)

Рисунок 5 — FindShortestPathWithAvoidance

Заключение

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

Приложение а

(обязательное)

Код программы

using System;

using System.Collections.Generic;

using System.Linq;

class Graph

{

private int[,] adjMatrix;

private int numCities;

public Graph(int numCities)

{

if (numCities <= 0)

{

throw new ArgumentException("Количество городов должно быть больше нуля.");

}

this.numCities = numCities;

adjMatrix = new int[numCities, numCities];

// инит матрицы смежности

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

{

for (int j = 0; j < numCities; j++)

{

if (i == j)

adjMatrix[i, j] = 0;

else

adjMatrix[i, j] = int.MaxValue / 2;

}

}

}

public void AddEdge(int u, int v, int weight)

{

if (u >= numCities || v >= numCities || u < 0 || v < 0)

{

throw new IndexOutOfRangeException("Ошибка! Указанный город не существует.");

}

if (weight <= 0)

{

throw new ArgumentException("Расстояние между городами должно быть положительным числом.");

}

adjMatrix[u, v] = weight;

}

public void PrintAdjMatrix()

{

Console.WriteLine("Матрица смежности:");

Console.Write(" ");

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

{

Console.Write($"{i}\t");

}

Console.WriteLine();

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

{

Console.Write($"{i}: ");

for (int j = 0; j < numCities; j++)

{

if (adjMatrix[i, j] == int.MaxValue / 2)

Console.Write("INF\t");

else

Console.Write(adjMatrix[i, j] + "\t");

}

Console.WriteLine();

}

}

// Алгоритм Дейкстры с исключением вершин

public (int distance, List<int> path) FindShortestPathWithAvoidance(int start, int end, int[] avoidedCities)

{

// Проверка корректности входных данных

if (start < 0 || start >= numCities || end < 0 || end >= numCities)

throw new ArgumentException("Неверные начальный или конечный город");

if (avoidedCities == null)

avoidedCities = new int[0];

// Массивы для хранения расстояний и предков

int[] dist = new int[numCities];

int[] prev = new int[numCities];

bool[] visited = new bool[numCities];

// Инициализация

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

{

dist[i] = int.MaxValue / 2;

prev[i] = -1;

}

dist[start] = 0;

// Основной цикл алгоритма Дейкстры

for (int count = 0; count < numCities - 1; count++)

{

// Находим вершину с минимальным расстоянием, которую ещё не посетили и которую не нужно избегать

int u = -1;

int minDist = int.MaxValue / 2;

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

{

if (!visited[i] && !avoidedCities.Contains(i) && dist[i] < minDist)

{

minDist = dist[i];

u = i;

}

}

// Если не нашли подходящую вершину, выходим

if (u == -1)

break;

visited[u] = true;

// Обновляем расстояния до соседей

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

{

if (!visited[v] && !avoidedCities.Contains(v) &&

adjMatrix[u, v] != int.MaxValue / 2 &&

dist[u] + adjMatrix[u, v] < dist[v])

{

dist[v] = dist[u] + adjMatrix[u, v];

prev[v] = u;

}

}

}

// Восстанавливаем путь

List<int> path = new List<int>();

if (dist[end] != int.MaxValue / 2)

{

int current = end;

while (current != -1)

{

path.Add(current);

current = prev[current];

}

path.Reverse();

}

return (dist[end], path);

}

// Метод Флойда-Уоршелла для поиска всех кратчайших путей

public int[,] FloydWarshall()

{

int[,] dist = new int[numCities, numCities];

Array.Copy(adjMatrix, dist, numCities * numCities);

for (int k = 0; k < numCities; k++)

{

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

{

for (int j = 0; j < numCities; j++)

{

if (dist[i, k] != int.MaxValue / 2 && dist[k, j] != int.MaxValue / 2 &&

dist[i, j] > dist[i, k] + dist[k, j])

{

dist[i, j] = dist[i, k] + dist[k, j];

}

}

}

}

return dist;

}

class Program

{

static void Main(string[] args)

{

try

{

Console.Write("Сколько городов (узлов)? ");

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

Graph graph = new Graph(numCities);

Console.Write("Сколько дорог (рёбер)? ");

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

for (int i = 1; i <= numRoads; i++)

{

bool running = true;

while (running)

{

try

{

Console.WriteLine($"Ввод для дороги {i}: введите начальный город, конечный город и расстояние в формате X,Y,Z");

string input = Console.ReadLine();

string[] parts = input.Split(',');

if (parts.Length != 3)

{

throw new FormatException("Неверный формат ввода. Используйте формат X,Y,Z.");

}

int u = int.Parse(parts[0]);

int v = int.Parse(parts[1]);

int weight = int.Parse(parts[2]);

graph.AddEdge(u, v, weight);

running = false;

}

catch (FormatException ex)

{

Console.WriteLine($"Ошибка формата: {ex.Message}. Повторите ввод.");

}

catch (ArgumentException ex)

{

Console.WriteLine($"Ошибка аргумента: {ex.Message}. Повторите ввод.");

}

catch (IndexOutOfRangeException ex)

{

Console.WriteLine($"Ошибка индекса: {ex.Message}. Повторите ввод.");

}

}

}

graph.PrintAdjMatrix();

// Поиск кратчайшего пути с исключением городов

Console.Write("Введите начальный город: ");

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

Console.Write("Введите конечный город: ");

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

Console.Write("Введите города для исключения (через запятую, Enter для пропуска): ");

string avoidInput = Console.ReadLine();

int[] avoidedCities;

if (string.IsNullOrWhiteSpace(avoidInput))

{

avoidedCities = new int[0];

}

else

{

avoidedCities = avoidInput

.Split(',')

.Select(s => s.Trim())

.Where(s => !string.IsNullOrEmpty(s))

.Select(int.Parse)

.ToArray();

}

var result = graph.FindShortestPathWithAvoidance(start, end, avoidedCities);

if (result.distance == int.MaxValue / 2)

{

Console.WriteLine("Путь не существует!");

}

else

{

Console.WriteLine($"Кратчайшее расстояние: {result.distance}");

Console.WriteLine($"Путь: {string.Join(" -> ", result.path)}");

}

}

catch (Exception ex)

{

Console.WriteLine($"Произошла ошибка: {ex.Message}");

}

}

}

}

Томск 2025

Соседние файлы в папке Практики(Вариант №7)