Обход в ширину

This commit is contained in:
Морозов Андрей 2021-10-26 10:56:10 +00:00
parent 312c6d3a85
commit d0d0e4398d
1 changed files with 116 additions and 7 deletions

View File

@ -255,7 +255,7 @@ class Graphs {
return null;
}
List<List<int>>? getTable() {
List<List<int>>? getLenTable() {
List<List<int>>? out = <List<int>>[];
for (int i = 0; i < _amount; i++) {
List<int> xx = <int>[];
@ -266,6 +266,22 @@ class Graphs {
}
return out;
}
List<List<int>>? getPathTable() {
List<List<int>>? out = <List<int>>[];
for (int i = 0; i < _amount; i++) {
List<int> xx = <int>[];
for (int j = 1; j <= _amount; j++) {
if (_dots[i].getLength(j) != -1) {
xx.add(i);
} else {
xx.add(-1);
}
}
out.add(xx);
}
return out;
}
//*****Getters*******
//******Print******
@ -316,11 +332,14 @@ class Graphs {
//******Print******
//*******Constructor********
Graphs() {
_name = "Udefined";
Graphs(
[String name = "Undefined",
bool hasLen = false,
bool isOriented = false]) {
_name = name;
_dots = <Dot>[];
_useLength = false;
_oriented = false;
_useLength = hasLen;
_oriented = isOriented;
_amount = 0;
_nameTable = <int, String>{};
}
@ -338,8 +357,8 @@ class Graphs {
File file = File(path);
List<String> lines = file.readAsLinesSync();
_name = lines.removeAt(0);
_oriented = lines.removeAt(0) == sep.isOriented;
_useLength = lines.removeAt(0) == sep.hasLength;
_oriented = lines.removeAt(0) == sep.isOriented.trim();
_useLength = lines.removeAt(0) == sep.hasLength.trim();
_dots = <Dot>[];
for (var l in lines) {
if (l != sep.end) {
@ -373,4 +392,94 @@ class Graphs {
_amount = _dots.length;
_syncNameTable();
}
//************Алгоритмы************
bool bfsHasPath(int startDot, int goalDot) {
// обход в ширину
startDot--;
goalDot--;
List<bool> visited = <bool>[];
List<int> queue = <int>[];
for (int i = 0; i < _amount; i++) {
visited.add(false);
} // изначально список посещённых узлов пуст
queue.add(startDot); // начиная с узла-источника
visited[startDot] = true;
while (queue.isNotEmpty) {
// пока очередь не пуста
int node = queue.removeAt(0); // извлечь первый элемент в очереди
if (node == goalDot) {
return true; // проверить, не является ли текущий узел целевым
}
for (int child in _dots[node].getL().keys) {
// все преемники текущего узла, ...
if (!visited[child - 1]) {
// ... которые ещё не были посещены ...
queue.add(child - 1); // ... добавить в конец очереди...
visited[child - 1] = true; // ... и пометить как посещённые
}
}
}
return false; // Целевой узел недостижим
}
List<int>? bfsPath(int startDot, int goalDot) {
//if (!bfsHasPath(startDot, goalDot)) return null;
startDot--;
goalDot--;
List<List<int>>? graph = getLenTable();
List<bool> used = <bool>[];
List<int> dst = <int>[];
List<int> pr = <int>[];
for (int i = 0; i < _amount; i++) {
dst.add(-1);
used.add(false);
pr.add(0);
}
List<int> q = <int>[];
q.add(startDot);
used[startDot] = true;
dst[startDot] = 0;
pr[startDot] =
-1; //Пометка, означающая, что у вершины startDot нет предыдущей.
while (q.isNotEmpty) {
int cur = q.removeAt(0);
int x = 0;
for (int neighbor in graph![cur]) {
if (neighbor != -1) {
if (!used[x]) {
q.add(x);
used[x] = true;
dst[x] = dst[cur] + 1;
pr[x] = cur; //сохранение предыдущей вершины
}
}
x++;
}
}
//Восстановим кратчайший путь
//Для восстановления пути пройдём его в обратном порядке, и развернём.
List<int> path = <int>[];
int cur = goalDot; //текущая вершина пути
path.add(cur + 1);
while (pr[cur] != -1) {
//пока существует предыдущая вершина
cur = pr[cur]; //переходим в неё
path.add(cur + 1); //и дописываем к пути
}
path = path.reversed.toList();
//print("Shortest path between vertices ${startDot+1} and ${goalDot+1} is: $path");
if (path[0]==startDot && path[1]==goalDot && !_dots[startDot].hasConnection(goalDot+1)) return null;
return path;
}
//************Алгоритмы************
}