Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Коды основных функций / [Код основных функций] Лаб. 5

.pdf
Скачиваний:
37
Добавлен:
03.08.2020
Размер:
57.41 Кб
Скачать

[Код основных функций] Лабораторная работа №5. Кратчайший путь в графе

//Get the current time.

//This function should be used only for measuring time

//(first call, algorithm, second call; then the difference between the values) double getProcTime() {

#if defined(_WIN32) // If Windows:

FILETIME createTime, exitTime, kernelTime, userTime;

if (GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime) != -1)

return (ULARGE_INTEGER { {userTime.dwLowDateTime, userTime.dwHighDateTime } }).QuadPart / 10000000.L;

return 0;

#else // If Linux or MacOS:

return double(clock()) / CLOCKS_PER_SEC; #endif

}

/* Input:

vector<vector<float>> matrix { {0, 1.5, 0, 0, 0, 0, 0}, {1, 0.0, 1.5, 9, 9, 9, 9}, {0, 1.0, 0, 1.5, 9, 9, 9}, {0, 9, 1.0, 0, 1.5, 9, 9}, {0, 9, 9, 1.0, 0, 1.5, 9}, {0, 9, 9, 9, 1.0, 0, 1.5}, {0, 9, 9, 9, 9, 1.0, 0.0}

};

Output:

Dijkstra's algorithm:

Vector of distances: 0.000000 1.500000 3.000000 4.500000 6.000000 7.500000 9.000000

Vector of parents: 0 0 1 2 3 4 5 Bellman-Ford algorithm:

Vector of distances: 0.000000 1.500000 3.000000 4.500000 6.000000 7.500000 9.000000

Vector of parents: 0 0 1 2 3 4 5 Levit's algorithm:

Vector of distances: 0.000000 1.500000 3.000000 4.500000 6.000000 7.500000 9.000000

Vector of parents: 0 0 1 2 3 4 5

*/

// Dijkstra's algorithm template <class T = int>

std::pair<std::vector<T>, std::vector<int>> dijkstraAlgorithm(const std::vector<std::vector<T>> & matrix, int start) {

const T INF = std::numeric_limits<T>::max(); const int n = matrix.size();

std::vector<T> distance(n, INF); std::vector<int> parent(n, -1); distance[parent[start] = start] = 0; std::priority_queue<std::pair<T, int>> q; q.push({ 0, start });

while (!q.empty()) {

T dist = -q.top().first; int v = q.top().second; q.pop();

if (dist > distance[v]) continue;

for (int to = 0, len = matrix[v].size(); to < len; ++to) { dist = matrix[v][to];

if (dist > 0 && distance[v] + dist < distance[to]) { distance[to] = distance[parent[to] = v] + dist; q.push({ -distance[to], to });

}

}

}

return { distance, parent };

}

// Bellman-Ford algorithm template <class T = int>

std::pair<std::vector<T>, std::vector<int>> bellmanFordAlgorithm(const std::vector<std::vector<T>> & matrix, int start) {

const T INF = std::numeric_limits<T>::max(); const int n = matrix.size();

std::vector<T> distance(n, INF); std::vector<int> parent(n, -1); distance[parent[start] = start] = 0; bool any;

do {

any = false;

for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) {

T dist = matrix[i][j];

if (dist > 0 && dist + distance[i] < distance[j]) { distance[j] = dist + distance[parent[j] = i]; any = true;

}

}

}

} while (any);

return { distance, parent };

}

// Levit's algorithm template <class T = int>

std::pair<std::vector<T>, std::vector<int>> levitAlgorithm(const

std::vector<std::vector<T>> & matrix, int start) { const T INF = std::numeric_limits<T>::max(); const int n = matrix.size();

std::vector<T> distance(n, INF); std::vector<int> parent(n, -1); std::vector<char> state(n, 2); distance[parent[start] = start] = 0; state[start] = 1;

std::deque<int> q(1, start); while (!q.empty()) {

int from = q.front(); q.pop_front(); state[from] = 0;

for (int to = 0, len = matrix[from].size(); to < len; ++to) { T dist = matrix[from][to];

if (dist > 0 && distance[to] > distance[from] + dist) { distance[to] = distance[parent[to] = from] + dist; if (state[to] == 2) q.emplace_front(to);

else if (state[to] == 0) q.emplace_back(to); state[to] = 1;

}

}

}

return { distance, parent };

}

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