-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathDijkstra.sol
More file actions
72 lines (63 loc) · 3.67 KB
/
Copy pathDijkstra.sol
File metadata and controls
72 lines (63 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
/**
* @title Алгоритм Дейкстры
* @notice Контракт реализует функцию search(),
* которая выполняет поиск кратчайшего пути до любой точки графа
*/
contract Dijkstra {
/**
* @notice Вызывает алгоритм поиска кратчайшего пути
* @param graph граф, в котором будет производиться поиск
* @param startNodeId Идентификатор узла с которого будет начинаться поиск
* @dev Считаем что все узлы графа пронумерованы от 0 до graph.length
* Если до узла будет невозможно добраться, то возвращаемое значение будет равняться type(uint256).max
*/
function search(uint256[][] memory graph, uint256 startNodeId) public pure returns (uint256[] memory) {
/// Массив для учета минимального расстояние, чтобы добраться до узла
uint256[] memory nodeWeights = new uint256[](graph.length);
/// Массив для учета посещенных узлов. Это поможет избежать зацикливания
bool[] memory visited = new bool[](graph.length);
/// Проставляем все результирующие значения в максимально возможные.
/// Это необходимо для поиска минимального пути до каждого узла графа
for (uint256 i = 0; i < graph.length; i++) {
nodeWeights[i] = type(uint256).max;
}
/// Расстояние из начального узла до начального равняется нулю. Закрепляем это сразу.
nodeWeights[startNodeId] = 0;
/// Обходим все узлы графа
uint256 count = graph.length;
while(count > 0) {
/// Находим минимальный путь до ближайшего соседнего узла графа и устанавливаем такой узел начальным
startNodeId = _findMinWeight(nodeWeights, visited);
visited[startNodeId] = true;
/// Считаем все возможные расстояния до ближайших соседних узлов.
for (uint256 endNodeId = 0; endNodeId < graph.length; endNodeId++) {
if (
!visited[endNodeId]
&& graph[startNodeId][endNodeId] != 0
&& nodeWeights[startNodeId] != type(uint256).max
&& nodeWeights[startNodeId] + graph[startNodeId][endNodeId] < nodeWeights[endNodeId]
) {
/// Обновляем расстояние, если оно меньше, чем было установлено ранее
nodeWeights[endNodeId] = nodeWeights[startNodeId] + graph[startNodeId][endNodeId];
}
}
count--;
}
return nodeWeights;
}
function _findMinWeight(uint256[] memory nodeWeights, bool[] memory visited)
private
pure
returns (uint256 nodeId)
{
uint256 minWeight = type(uint256).max;
for (uint256 i = 0; i < nodeWeights.length; i++) {
if (!visited[i] && nodeWeights[i] <= minWeight) {
minWeight = nodeWeights[i];
nodeId = i;
}
}
}
}