Приложение. Листинг программных модулей
#include <iostream>
#include <chrono>
#include <random>
#include <fstream>
#include <vector>
#include <climits>
#include <windows.h>
using namespace std;
using namespace chrono;
const int INF = INT_MAX / 2; // избегаем переполнения при сложении
// Генерация случайного графа
vector<vector<int>> generate_sparse_graph(int n, int avg_deg = 6) {
vector<vector<int>> g(n, vector<int>(n, INF));
for (int i = 0; i < n; i++) g[i][i] = 0;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> vertex_dist(0, n-1);
uniform_int_distribution<> weight_dist(1, 100);
int target_edges = n * avg_deg / 2;
int edges_added = 0;
while (edges_added < target_edges) {
int u = vertex_dist(gen);
int v = vertex_dist(gen);
if (u != v && g[u][v] == INF) {
int w = weight_dist(gen);
g[u][v] = g[v][u] = w;
edges_added++;
}
}
return g;
}
// Алгоритм Флойда-Уоршелла
void floyd_warshall(vector<vector<int>>& dist) {
int n = dist.size();
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
if (dist[i][k] == INF) continue;
for (int j = 0; j < n; ++j) {
if (dist[k][j] == INF) continue;
int new_d = dist[i][k] + dist[k][j];
if (new_d < dist[i][j])
dist[i][j] = new_d;
}
}
}
}
// Алгоритм Дейкстры
vector<int> dijkstra(const vector<vector<int>>& graph, int start) {
int n = graph.size();
vector<int> dist(n, INF);
vector<bool> visited(n, false);
dist[start] = 0;
for (int count = 0; count < n - 1; ++count) {
// Находим вершину с минимальным расстоянием среди необработанных
int u = -1;
int min_dist = INF;
for (int i = 0; i < n; ++i) {
if (!visited[i] && dist[i] < min_dist) {
min_dist = dist[i];
u = i;
}
}
if (u == -1) break; // остальные вершины недостижимы
visited[u] = true;
for (int v = 0; v < n; ++v) {
if (!visited[v] && graph[u][v] != INF) {
int new_d = dist[u] + graph[u][v];
if (new_d < dist[v])
dist[v] = new_d;
}
}
}
return dist;
}
int main() {
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
// Параметры эксперимента
const int START_VERTICES = 100;
const int MAX_VERTICES = 1000;
const int STEP = 50; // шаг увеличения числа вершин
const int REPEATS = 5; // сколько раз замеряем для каждого размера
const int AVG_DEGREE = 6; // средняя степень вершины
ofstream fout("results.csv");
fout << "Vertices,Floyd_ms,Dijkstra_ms\n";
cout << "Сравнение алгоритмов Флойда-Уоршелла и Дейкстры\n";
cout << "Граф разреженный (средняя степень " << AVG_DEGREE << ")\n";
cout << "Каждая точка усреднена по " << REPEATS << " запускам\n\n";
for (int n = START_VERTICES; n <= MAX_VERTICES; n += STEP) {
cout << "Тестирование для n = " << n << " ... " << flush;
double total_time_floyd = 0.0;
double total_time_dijkstra = 0.0;
for (int rep = 0; rep < REPEATS; ++rep) {
// Генерируем граф
vector<vector<int>> graph = generate_sparse_graph(n, AVG_DEGREE);
// Флойд-Уоршелл
vector<vector<int>> graph_floyd = graph; // копия
auto start_time = high_resolution_clock::now();
floyd_warshall(graph_floyd);
auto end_time = high_resolution_clock::now();
total_time_floyd += duration_cast<milliseconds>(end_time - start_time).count();
// Дейкстра
start_time = high_resolution_clock::now();
for (int s = 0; s < n; ++s) {
vector<int> dist = dijkstra(graph, s);
}
end_time = high_resolution_clock::now();
total_time_dijkstra += duration_cast<milliseconds>(end_time - start_time).count();
}
double avg_floyd = total_time_floyd / REPEATS;
double avg_dijkstra = total_time_dijkstra / REPEATS;
cout << " Флойд: " << avg_floyd << " ms, Дейкстра (n запусков): " << avg_dijkstra << " ms\n";
fout << n << "," << avg_floyd << "," << avg_dijkstra << "\n";
}
fout.close();
cout << "\nРезультаты сохранены в results.csv\n";
cout << "Для построения графика откройте файл в Excel или Google Sheets\n";
return 0;
}
