This commit is contained in:
Морозов Андрей 2021-11-24 21:35:55 +04:00
parent 682c4df7bd
commit 5175d15194
23 changed files with 496 additions and 80 deletions

52
tex/dart/graph/bfs.dart Normal file
View File

@ -0,0 +1,52 @@
List<int>? bfsPath(int startDot, int goalDot) {
if (startDot == goalDot) return [startDot];
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; //ó âåðøèíû íåò ïðåäûäóùåé.
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();
if (path[0] == (startDot + 1) &&
path[1] == (goalDot + 1) &&
!_dots[startDot].hasConnection(goalDot + 1)) return null;
return path;
}

19
tex/dart/graph/dfs.dart Normal file
View File

@ -0,0 +1,19 @@
List<bool>? dfsIterative(int v) {
v--;
List<bool> label = <bool>[];
for (int i = 0; i < _amount; i++) {
label.add(false);
}
List<int> stack = <int>[];
stack.add(v);
while (stack.isNotEmpty) {
v = stack.removeLast();
if (!label[v]) {
label[v] = true;
for (int i in _dots[v].getL().keys) {
stack.add(i - 1);
}
}
}
return label;
}

View File

@ -0,0 +1,29 @@
List<int?> dijkstra(int from) {
List<int?> d = List<int?>.filled(_amount, intMax);
List<int> p = List<int>.filled(_amount, -1);
d[from - 1] = 0;
List<bool> u = List<bool>.filled(_amount, false);
for (int i = 0; i < _amount; ++i) {
int v = -1;
for (int j = 0; j < _amount; ++j) {
if (!u[j] && (v == -1 || d[j]! < d[v]!)) {
v = j;
}
}
if (d[v] == intMax) break;
u[v] = true;
for (int to in _dots[v].getL().keys) {
int len = _dots[v].getL()[to]!;
if (!_useLength && len == 0) len = 1;
if (d[v]! + len < d[to - 1]!) {
d[to - 1] = d[v]! + len;
p[to - 1] = v;
}
}
}
for (int i = 0; i < d.length; i++) {
if (d[i] == intMax) d[i] = null;
}
return d;
}

6
tex/dart/graph/dot.dart Normal file
View File

@ -0,0 +1,6 @@
class Dot {
//Data
String _name = "";
int num = -1;
Map<int, int> _ln = <int, int>{};
***

View File

@ -0,0 +1,24 @@
Dot([String name = "Undefined", int n = -1]) {
_name = name;
num = n;
_ln = <int, int>{};
}
Dot.fromTwoLists(String name, List<int> num0, List<int> length,
[int n = -1]) {
_name = name;
num = n;
Map<int, int> nw = <int, int>{};
if (num0.length != length.length) {
print("Error in lists");
} else {
for (var i = 0; i < num0.length; i++) {
nw[num0[i]] = length[i];
_ln = nw;
}
}
}
Dot.fromMap(String name, Map<int, int> l, [int n = -1]) {
_name = name;
num = n;
_ln = l;
}

View File

@ -0,0 +1,5 @@
void setName(String n) => _name = n;
void addPath(int inp, int length) => _ln[inp] = length;
void delPath(int n) => _ln.removeWhere((key, value) => key == n);

View File

@ -0,0 +1,6 @@
String _name = "Undefined"; //Èìÿ
int _amount = 0; //Êîëè÷åñòâî âåðøèí
List<Dot> _dots = <Dot>[]; //Ñïèñîê ñìåæíîñòè âåðøèí
Map<int, String> _nameTable = <int, String>{}; //Ñïèñîê âåðøèí ïî èìåíàì
bool _useLength = false; //Âçâåøåííîñòü
bool _oriented = false; //Îðèåíòèðîâàííîñòü

View File

@ -0,0 +1,28 @@
Graphs? kruskal() {
List<LenDotPath> g = getSortedPathList();
//int cost = 0;
List<Dot> res = <Dot>[];
for (int i = 0; i < _amount; i++) {
res.add(Dot(_dots[i].getName(), _dots[i].num));
}
List<int> treeId = List<int>.filled(_amount, 0);
for (int i = 0; i < _amount; ++i) {
treeId[i] = i;
}
for (int i = 0; i < g.length; ++i) {
int a = g[i].d - 1, b = g[i].p - 1;
int l = g[i].l;
if (treeId[a] != treeId[b]) {
//cost += l;
res[a].addPath(b + 1, l);
int oldId = treeId[b], newId = treeId[a];
for (int j = 0; j < _amount; ++j) {
if (treeId[j] == oldId) {
treeId[j] = newId;
}
}
}
}
_dots = res;
return Graphs.fromList(_name, res, _useLength, _oriented);
}

58
tex/dart/page/build.dart Normal file
View File

@ -0,0 +1,58 @@
@override
Widget build(BuildContext context) {
screenSize = MediaQuery.of(context).size.width;
_textGrNmController.text = graphData.getName();
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Align(
alignment: Alignment.topLeft,
child: Text("Graph name:\n",
style: TextStyle(
fontSize: 18,
color: Colors.white,
))),
toolbarHeight: 110,
flexibleSpace: Container(
color: Colors.green.shade900,
child: Column(children: <Widget>[
/*
Îïèñàíèå ýëåìåíòîâ íà ïàíåëå ïðèëîæåíèÿ
*/
]),
),
actions: [
IconButton(
onPressed: () {
setState(() {
clearDropDownVals();
graphData.flushData();
clearInputData();
});
},
icon: const Icon(Icons.delete_sweep),
iconSize: 60,
),
]),
body: CustomPaint(
painter: CurvePainter(
graphData: graphData,
intListPath: intListPath,
dfsAccessTable: dfsAccessTable,
start: startDot,
end: endDot,
op: op),
child: Align(
alignment: Alignment.topRight,
child: ButtonBar(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/*
Îïèñàíèå êíîïîê äåéñòâèÿ
*/
],
),
),
),
));
}

14
tex/dart/page/button.dart Normal file
View File

@ -0,0 +1,14 @@
ElevatedButton createButton(String txt, void Function() onPressing) {
return ElevatedButton(
onPressed: onPressing,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(states) => Colors.green.shade700)),
child: Text(txt,
style: const TextStyle(
fontSize: 15,
color: Colors.white70,
height: 1,
)),
);
}

View File

@ -0,0 +1,22 @@
void _drawHArrow(Canvas canvas, Size size, Offset from, Offset to, [bool doubleSided = false]) {
Path path;
// The arrows usually looks better with rounded caps.
Paint paint = ... // çàäàåòñÿ ñòèëü
var length = sqrt((to.dx - from.dx) * (to.dx - from.dx) +
(to.dy - from.dy) * (to.dy - from.dy));
path = Path();
path.moveTo(from.dx, from.dy);
path.relativeCubicTo(
0,
0,
-(from.dx + to.dx + length) / (length) - 40,
-(from.dy + to.dy + length) / (length) - 40,
to.dx - from.dx,
to.dy - from.dy);
path =
ArrowPath.make(path: path, isDoubleSided: doubleSided, tipLength: 16);
canvas.drawPath(path, paint);
}

View File

@ -0,0 +1,9 @@
CurvePainter({
Key? key,
required this.graphData,
required this.intListPath,
required this.dfsAccessTable,
required this.start,
required this.end,
required this.op,
});

24
tex/dart/painter/pos.dart Normal file
View File

@ -0,0 +1,24 @@
Map<int, Offset> _getDotPos(int dotsAm, Size size) {
Map<int, Offset> off = <int, Offset>{};
var width = size.width / 2;
var height = size.height / 2;
int add = 0;
int h = _getHighInputConnections();
for (int i = 0; i < dotsAm; i++) {
if ((i + 1) != h) {
double x =
cos(2 * pi * (i - add) / (dotsAm - add)) * _circleRad + width;
double y =
sin(2 * pi * (i - add) / (dotsAm - add)) * _circleRad + height;
off[i + 1] = Offset(x, y);
} else if ((i + 1) == h) {
off[i + 1] = Offset(width + 2, height - 2);
add = 1;
h = 0;
} else {
print("GetDotPos error");
}
}
return off;
}

View File

@ -0,0 +1,9 @@
dijkstra (G, w, s):
source(G,s)
S <- null
Q <- V[G]
while Q!=null:
u <- Extract_min(Q)
s <- S + u
äë˙ ęŕćäîé âĺđřčíű v čç Adj[u]:
relax(u, v, w)

View File

@ -0,0 +1,10 @@
kruscal(G, w):
A <- null
for v èç V[G]:
create_set(v)
sort(E)
for (u, v) èç E:
if find_set(u) != find_set(v):
A <- A + {(u,v)}
return A

View File

@ -245,35 +245,49 @@ $$ E = \{(a, b), (a, c), (a, e), (b, c), (b, d), (c, e), (d, e)\}$$
Поиск в ширину имеет такое название потому, что в процессе обхода мы идём вширь, то есть перед тем как приступить к поиску вершин на расстоянии $k + 1$, выполняется обход вершин на расстоянии $k$~\cite{Algo_2013}.
Приведенная ниже процедура поиска в ширину BFS предполагает, что входной граф $G = (V, E)$ представлен при помощи списков смежности. Псевдокод:
Приведенная ниже процедура поиска в ширину BFS предполагает, что входной граф $G = (V, E)$ представлен при помощи списков смежности. Псевдокод алгоритма:
\inputminted[fontsize=\footnotesize, linenos]{python}{./dart/pseudoBFS.txt}
Воспользуемся групповым анализом. Операции внесения в очередь и удаление из нее требует $O(1)$ времени. Следовательно на очередь потребуется $O(V)$ времени. Т.к. максимальная длина списков смежности $\theta(E)$, то время, необходимое для сканирования списков, равно $O(E)$. Расходы на инициализацию: $O(V)$. Таким образом, общее время работы алгоритма: $O(V + E)$. Время поиска в ширину линейно зависит от размера представления графа.
\subsubsection{Обход в глубину}
Стратегия обхода в ширину состоит в том, чтобы идти ''вглубь'' графа. Сначала исследуются ребра, выходящие из вершины, открытой последней, и покидаем вершину, когда не остается неисследованных ребер --- при этом происходит возврат в вершину, из которой была открыта вершина $v$. Процесс продолжается, пока не будут открыты все вершины, достижимые из исходной.
Псевдо код алгоритма:
\inputminted[fontsize=\footnotesize, linenos]{python}{./dart/pseudoDFS.txt}
\subsubsection{Алгоритм Дейкстры}
Алгоритм был предложен голландским исследователем Эдсгером Дейкстрой в 1959 году. Используется для поиска кратчайшего пути от одной вершины до всех остальных. Используется только если вес ребер неотрицательный.
В алгоритме поддерживается множество вершин $U$, для которых уже вычислены длины кратчайших путей до них из $s$. На каждой итерации основного цикла выбирается вершина, которой на текущий момент соответствует минимальная оценка кратчайшего пути. Вершина $u$ добавляется в множество $U$ и производится релаксация всех исходящих из неё рёбер.
Псевдокод алгоритма:
\inputminted[fontsize=\footnotesize, linenos]{python}{./dart/pseudoDijkstra.txt}
\subsubsection{Алгоритм Краскала}
Алгоритм Краскала — алгоритм поиска минимального остовного дерева во взвешенном неориентированном связном графе. Был описан Джозефом Краскалом в 1956 году.
Алгоритм Крускала изначально помещает каждую вершину в своё дерево, а затем постепенно объединяет эти деревья, объединяя на каждой итерации два некоторых дерева некоторым ребром. Перед началом выполнения алгоритма, все рёбра сортируются по весу (в порядке неубывания). Затем начинается процесс объединения: перебираются все рёбра от первого до последнего (в порядке сортировки), и если у текущего ребра его концы принадлежат разным поддеревьям, то эти поддеревья объединяются, а ребро добавляется к ответу. По окончании перебора всех рёбер, все вершины окажутся принадлежащими одному поддереву.\cite{krusc}
\inputminted[fontsize=\footnotesize, linenos]{python}{./dart/pseudoKruscal.txt}
\section{Инструменты}
Рассмотрим используемый язык и библиотеку для отрисовки.
\subsection{Dart}
В качестве основы используется язык \textbf{Dart}, разработанный компанией Google, и широко используемый для кросс-платформенной разработки~\cite{dart_web}.
Dart позиционируется в качестве замены/альтернативы JavaScript. Один из разработчиков языка Марк Миллер (Mark S. Miller) написал, что JavaScript «имеет фундаментальные изъяны»\cite{futureOfJavascript} («Javascript has fundamental flaws…»), которые невозможно исправить.
Dart позиционируется в качестве замены/альтернативы JavaScript. Один из разработчиков языка Марк Миллер (Mark S. Miller) писал, что JavaScript «имеет фундаментальные изъяны»\cite{futureOfJavascript}, которые невозможно исправить.
Версия 1.0 вышла в 14 ноября 2013 года.
Вторая версия была выпущена в августе 2018 года. В языке появилась надежная система типов, т.~е. во время выполнении программы все переменные будут гарантированно указанному типу~\cite{dart_sound}.
В Dart используется сборщик мусора. Синтаксис похож на языки: JavaScript, C\#, Java~\cite{dartInAction}.
Пример HelloWorld на Dart:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/helloWorld.dart}
Dart поддерживает сокращенную запись. Код примера HelloWorld можно записать так:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/hW.dart}
Концепты языка~\cite{dart_tour}:
\begin{itemize}
\item Все, что можно поместить в переменную, является объектом, а каждый объект является частью класса;
@ -283,7 +297,6 @@ Dart
\item для объявления локальных функций и переменных необходимо начать имя со знака ''\_''
\end{itemize}
.
\subsection{Flutter}
Для отрисовки информации используется фреймворк c открытым исходным кодом ''Flutter'', разработанный компанией Google.
Flutter не использует нативные компоненты для отрисовки интерфейса. В его основе лежит графический движок ''Skia'', написанный преимущественно на С++.
@ -299,48 +312,139 @@ Skia ---
\caption{\label{fig:flutter_example}
Простейшее приложение на Flutter}
\end{figure}
Интерфейс описывается с помощью виджетов.
\section{Реализация}
Структура программы разбита на 4 файла:
\begin{itemize}
\item main.dart --- точка входа в программу;
\item drawing\_page.dart --- страница с описанием работы кнопок;
\item curve\_painter.dart --- функционал для отрисовки графа;
\item graph.dart --- класс для хранения графа и манипуляции с ним.
\end{itemize}
\subsection{Графы}
\subsubsection{Класс для вершины}
\subsubsection{Класс для графа}
Информация хранится в виде списков смежности.
Полный код можно посмотреть в приложении~\ref{graph}.
\subsubsection{Класс для хранения вершины}
Класс \textbf{Dot} используется для хранения информации о ребрах, исходящих из данной вершины.
Основная информация:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/dot.dart}
\textit{String \_name} используется для хранения имени, \textit{int num} используется для хранения номера вершины.
Информация о ребрах задается в виде \textit{Map<int, int> \_ln}, где каждой вершине можно присвоить вес ребра.
Создать вершину можно тремя способами:
\begin{enumerate}
\item Пустая точка;
\item из двух списков, где в первом список вершин, а во втором - длины пути;
\item из \textit{Map<int, int>}.
\end{enumerate}
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/dot_constr.dart}
Для манипуляций с информацией доступно:
\begin{enumerate}
\item изменение имени;
\item добавление пути;
\item удаление пути.
\end{enumerate}
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/dot_manip.dart}
\subsubsection{Класс для графов}
Класс \textbf{Graphs} используется для хранения точек и манипуляции с ними.
Основная информация:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/graph.dart}
\textit{String \_name} исользуется для имени графа, \textit{int \_amount} --- количество вершин, \textit{List<Dot> \_dots} --- массив точек, \textit{Map<int, String> \_nameTable} --- отслеживание имени каждой вершины, \textit{bool \_useLength} --- отслеживание взвешенности графа, \textit{bool \_oriented} --- отслеживание ориентированности графа.
Для работы графом доступны функции:
\begin{enumerate}
\item \textbf{String? addDot(Dot a)} --- добавление вершины;
\item \textbf{String? addIsolated(String name)} --- добавление изолированной точки;
\item \textbf{String? addPath(int from, int to, [int len = 0])} --- добавление пути;
\item \textbf{String? delPath(int from, int to)} --- удаление пути;
\item \textbf{String? delDot(int inn)} --- удаление вершины;
\item \textbf{void flushData()} --- удаление информации из графа;
\item \textbf{bool checkDots([bool verbose = false])} --- проверка графа на ошибки;
\item \textbf{void \_fixAfterDel(int inn}) --- испралвение нумерации после удаления;
\item \textbf{void \_syncNameTable()} --- синхронизация таблицы имен вершин;
\item \textbf{void setName(String name)} --- изменение имени;
\item \textbf{String? replaceDataFromFile(String path)} --- заменяет информацию графа на информацию из файла;
\item \textbf{List<LenDotPath> getSortedPathList()} --- возвращает список всех путей, отсортированный в порядке неубывания;
\item \textbf{void printG()} --- выводит информацию о графе в консоль;
\item \textbf{void printToFile(String name)} --- выводит информацию о графе в файл;
\end{enumerate}
Создать граф можно тремя способами:
\begin{enumerate}
\item пустой граф;
\item из списка смежности;
\item из файла.
\end{enumerate}
\subsubsection{Алгоритмы}
\subsubsection{Кнопки}
Алгоритмы описаны в классе графа.\newline
Обход в ширину:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/bfs.dart}
Обход в глубину:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/dfs.dart}
Алгоритм Дейкстры:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/dijkstra.dart}
Алгоритм Краскала:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/graph/kruscal.dart}
\subsubsection{Интерфейс}
Интерфейс описан в файле drawing\_page.dart. Полный код доступен в приложении~\ref{buttons}.
Интерфейс программы:
\begin{figure}[!ht]
\centering
\includegraphics[width=9cm]{./pic/grafs.png}
\caption{\label{fig:programm}
Интерфейс программы}
\end{figure}
\newpage
В качестве основы выбран виджет, сохраняющий состояние.
Построение интерфейса:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/page/build.dart}
Запуск работы алгоритмов происходит по нажатию соответствующих кнопок, затем страница отрисовки, используя полученные данные, отрисовывает на экране информацию.
\subsubsection{Отрисовка графа}
Отрисовка графа описана в файле curve\_painter.dart. Код доступен в приложении~\ref{painter}.
\section{Таблица}
\subsection{Текст с таблицей}
Для отрисовки информации используется виджет CustomPaint~\cite{custompaint}.
\begin{table}[!ht]
\small
\caption{Результат сокращения словарей неисправностей при помощи масок} \label{table-1}
\begin{tabular}{|l|c|c|c|c|r|r|r|}
\hline 1 & 2& 3& 4& 5& 6& 7& 8\\
\hline S298 & 177 & 1932 & 341964 & 61 & 10797 & 3,16\% & 0,61\\
\hline S344 & 240 & 1397 & 335280 & 59 & 14160 & 4,22\% & 0,53\\
\hline S349 & 243 & 1474 & 358182 & 62 & 15066 & 4,21\% & 0,60\\
\hline S382 & 190 & 12444 & 2364360 & 55 & 10450 & 0,44\% & 3,78\\
\hline S386 & 274 & 2002 & 548548 & 91 & 24934 & 4,55\% & 1,40\\
\hline S400 & 194 & 13284 & 2577096 & 58 & 11252 & 0,44\% & 4,28\\
\hline S444 & 191 & 13440 & 2567040 & 60 & 11460 & 0,45\% & 4,26\\
\hline S510 & 446 & 700 & 312200 & 70 & 31220 & 10,00\% & 0,63\\
\hline S526 & 138 & 13548 & 1869624 & 38 & 5244 & 0,28\% & 2,41\\
\hline S641 & 345 & 5016 & 1730520 & 132 & 45540 & 2,63\% & 7,06\\
\hline S713 & 343 & 3979 & 1364797 & 131 & 44933 & 3,29\% & 5,61\\
\hline S820 & 712 & 21185 & 15083720 & 244 & 173728 & 1,15\% & 126,99\\
\hline S832 & 719 & 21603 & 15532557 & 253 & 181907 & 1,17\% & 135,18\\
\hline S953 & 326 & 322 & 104972 & 91 & 29666 & 28,26\% & 0,27\\
\hline S1423 & 293 & 750 & 219750 & 93 & 27249 & 12,40\% & 0,57\\
\hline S1488 & 1359 & 22230 & 30210570 & 384 & 521856 & 1,73\% & 541,69\\
\hline
\end{tabular}
\end{table}
Для передачи информации графа используется конструктор CurvePainter.
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/painter/constr.dart}
Отрисовка соединений происходит с помощью пакета ''arrow\_path''.
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/painter/arrow.dart}
Для упрощения отрисовки, точки располагаются на окружности с центом, совпадающим с центром экрана. Сначала вычисляется их местоположение на экране, точка с максимальным количеством соединений располагается в центре:
\inputminted[fontsize=\footnotesize, linenos]{dart}{./dart/painter/pos.dart}
Процесс вывода на экран:
\begin{enumerate}
\item вывод вершин на экран;
\item определение текущей операции и вывод работы текущего алгоритма;
\item вывод ребер;
\item вывод длин ребер;
\item вывод имен вершин.
\end{enumerate}
\subsubsection{Итоговый вид приложения}
Итоговое приложение выглядит так:
\begin{figure}[!ht]
\centering
\includegraphics[width=15cm]{./pic/result.png}
\caption{\label{fig:resutl}
Интерфейс программы}
\end{figure}
\newpage
% Раздел "Заключение"
\conclusion
Было разработано простое приложение для создания и работы с графами с использованием Dart и Flutter.
В приложении возможно:
В приложении возможно с помощью графического интерфейса:
\begin{itemize}
\item создать пустой граф;
\item добавить вершину;
@ -349,20 +453,13 @@ Skia ---
\item удалить путь;
\item сохранить граф;
\item загрузить граф;
\item построить минимальное остовное дерево с помощью алгоритма Крускала;
\item построить минимальное остовное дерево с помощью алгоритма Краскала;
\item найти минимальный путь из выбранной вершины в другие с помощью алгоритма Дейкстры;
\item проверить доступность вершин с помощью обхода в глубину;
\item построить путь из одной вершины в другую с помощью обхода в ширину.
\end{itemize}
%Библиографический список, составленный вручную, без использования BibTeX
%
%\begin{thebibliography}{99}
% \bibitem{Ione} Источник 1.
% \bibitem{Itwo} Источник 2
%\end{thebibliography}
%Библиографический список, составленный с помощью BibTeX
%
\bibliographystyle{gost780uv}

View File

@ -8,22 +8,29 @@
\contentsline {subsubsection}{\numberline {1.3.2}\IeC {\CYRM }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrc }\IeC {\cyra } \IeC {\cyrs }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrzh }\IeC {\cyrn }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyri }}{6}{subsubsection.1.3.2}%
\contentsline {subsubsection}{\numberline {1.3.3}\IeC {\CYRM }\IeC {\cyra }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrc }\IeC {\cyra } \IeC {\cyri }\IeC {\cyrn }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyrd }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyrt }\IeC {\cyrn }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyri }}{6}{subsubsection.1.3.3}%
\contentsline {subsubsection}{\numberline {1.3.4}\IeC {\CYRS }\IeC {\cyrp }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyrk }\IeC {\cyri } \IeC {\cyrs }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrzh }\IeC {\cyrn }\IeC {\cyro }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyri }}{7}{subsubsection.1.3.4}%
\contentsline {section}{\numberline {2}\IeC {\CYRI }\IeC {\cyrn }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyru }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyrt }\IeC {\cyrery }}{8}{section.2}%
\contentsline {subsection}{\numberline {2.1}Dart}{8}{subsection.2.1}%
\contentsline {subsection}{\numberline {2.2}Flutter}{8}{subsection.2.2}%
\contentsline {section}{\numberline {3}\IeC {\CYRR }\IeC {\cyre }\IeC {\cyra }\IeC {\cyrl }\IeC {\cyri }\IeC {\cyrz }\IeC {\cyra }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyrya }}{8}{section.3}%
\contentsline {subsection}{\numberline {3.1}\IeC {\CYRT }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrs }\IeC {\cyrt } \IeC {\cyrs } \IeC {\cyrf }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyrm }\IeC {\cyru }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrm }\IeC {\cyri } \IeC {\cyri } \IeC {\cyrl }\IeC {\cyre }\IeC {\cyrm }\IeC {\cyrm }\IeC {\cyro }\IeC {\cyrishrt }}{8}{subsection.3.1}%
\contentsline {subsection}{\numberline {3.2}\IeC {\CYRN }\IeC {\cyra }\IeC {\cyrz }\IeC {\cyrv }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyre } \IeC {\cyrd }\IeC {\cyrr }\IeC {\cyru }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyro } \IeC {\cyrp }\IeC {\cyro }\IeC {\cyrd }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrz }\IeC {\cyrd }\IeC {\cyre }\IeC {\cyrl }\IeC {\cyra }}{8}{subsection.3.2}%
\contentsline {subsubsection}{\numberline {3.2.1}\IeC {\CYRB }\IeC {\cyro }\IeC {\cyrl }\IeC {\cyre }\IeC {\cyre } \IeC {\cyrm }\IeC {\cyre }\IeC {\cyrl }\IeC {\cyrk }\IeC {\cyri }\IeC {\cyrishrt } \IeC {\cyrp }\IeC {\cyro }\IeC {\cyrd }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrz }\IeC {\cyrd }\IeC {\cyre }\IeC {\cyrl }}{8}{subsubsection.3.2.1}%
\contentsline {subsubsection}{\numberline {3.2.2}\IeC {\CYRT }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrs }\IeC {\cyrt } \IeC {\cyrs } \IeC {\cyrt }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyrl }\IeC {\cyri }\IeC {\cyrc }\IeC {\cyre }\IeC {\cyrishrt }}{8}{subsubsection.3.2.2}%
\contentsline {subsubsection}{\numberline {3.2.3}\IeC {\CYRT }\IeC {\cyre }\IeC {\cyrk }\IeC {\cyrs }\IeC {\cyrt } \IeC {\cyrs } \IeC {\cyrk }\IeC {\cyro }\IeC {\cyrd }\IeC {\cyro }\IeC {\cyrm } \IeC {\cyrp }\IeC {\cyrr }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrm }\IeC {\cyrm }\IeC {\cyrery }}{8}{subsubsection.3.2.3}%
\contentsline {section}{\cyrillictext \CYRZ \CYRA \CYRK \CYRL \CYRYU \CYRCH \CYRE \CYRN \CYRI \CYRE }{8}{section*.8}%
\contentsline {section}{\cyrillictext \CYRS \CYRP \CYRI \CYRS \CYRO \CYRK \ \CYRI \CYRS \CYRP \CYRO \CYRL \CYRSFTSN \CYRZ \CYRO \CYRV \CYRA \CYRN \CYRN \CYRERY \CYRH \ \CYRI \CYRS \CYRT \CYRO \CYRCH \CYRN \CYRI \CYRK \CYRO \CYRV }{10}{section*.9}%
\contentsline {subsection}{\numberline {1.4}\IeC {\CYRA }\IeC {\cyrl }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrt }\IeC {\cyrm }\IeC {\cyrery }}{7}{subsection.1.4}%
\contentsline {subsubsection}{\numberline {1.4.1}\IeC {\CYRO }\IeC {\cyrb }\IeC {\cyrh }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrv } \IeC {\cyrsh }\IeC {\cyri }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrn }\IeC {\cyru }}{7}{subsubsection.1.4.1}%
\contentsline {subsubsection}{\numberline {1.4.2}\IeC {\CYRO }\IeC {\cyrb }\IeC {\cyrh }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrv } \IeC {\cyrg }\IeC {\cyrl }\IeC {\cyru }\IeC {\cyrb }\IeC {\cyri }\IeC {\cyrn }\IeC {\cyru }}{8}{subsubsection.1.4.2}%
\contentsline {subsubsection}{\numberline {1.4.3}\IeC {\CYRA }\IeC {\cyrl }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrt }\IeC {\cyrm } \IeC {\CYRD }\IeC {\cyre }\IeC {\cyrishrt }\IeC {\cyrk }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyrery }}{9}{subsubsection.1.4.3}%
\contentsline {subsubsection}{\numberline {1.4.4}\IeC {\CYRA }\IeC {\cyrl }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrt }\IeC {\cyrm } \IeC {\CYRK }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrk }\IeC {\cyra }\IeC {\cyrl }\IeC {\cyra }}{9}{subsubsection.1.4.4}%
\contentsline {section}{\numberline {2}\IeC {\CYRI }\IeC {\cyrn }\IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyru }\IeC {\cyrm }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyrt }\IeC {\cyrery }}{11}{section.2}%
\contentsline {subsection}{\numberline {2.1}Dart}{11}{subsection.2.1}%
\contentsline {subsection}{\numberline {2.2}Flutter}{12}{subsection.2.2}%
\contentsline {section}{\numberline {3}\IeC {\CYRR }\IeC {\cyre }\IeC {\cyra }\IeC {\cyrl }\IeC {\cyri }\IeC {\cyrz }\IeC {\cyra }\IeC {\cyrc }\IeC {\cyri }\IeC {\cyrya }}{14}{section.3}%
\contentsline {subsection}{\numberline {3.1}\IeC {\CYRG }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyrery }}{14}{subsection.3.1}%
\contentsline {subsubsection}{\numberline {3.1.1}\IeC {\CYRK }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrs } \IeC {\cyrd }\IeC {\cyrl }\IeC {\cyrya } \IeC {\cyrh }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyrya } \IeC {\cyrv }\IeC {\cyre }\IeC {\cyrr }\IeC {\cyrsh }\IeC {\cyri }\IeC {\cyrn }\IeC {\cyrery }}{14}{subsubsection.3.1.1}%
\contentsline {subsubsection}{\numberline {3.1.2}\IeC {\CYRK }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrs } \IeC {\cyrd }\IeC {\cyrl }\IeC {\cyrya } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyro }\IeC {\cyrv }}{15}{subsubsection.3.1.2}%
\contentsline {subsubsection}{\numberline {3.1.3}\IeC {\CYRA }\IeC {\cyrl }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrt }\IeC {\cyrm }\IeC {\cyrery }}{16}{subsubsection.3.1.3}%
\contentsline {subsubsection}{\numberline {3.1.4}\IeC {\CYRI }\IeC {\cyrn }\IeC {\cyrt }\IeC {\cyre }\IeC {\cyrr }\IeC {\cyrf }\IeC {\cyre }\IeC {\cyrishrt }\IeC {\cyrs }}{19}{subsubsection.3.1.4}%
\contentsline {subsubsection}{\numberline {3.1.5}\IeC {\CYRO }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyra } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyra }}{21}{subsubsection.3.1.5}%
\contentsline {subsubsection}{\numberline {3.1.6}\IeC {\CYRI }\IeC {\cyrt }\IeC {\cyro }\IeC {\cyrg }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrery }\IeC {\cyrishrt } \IeC {\cyrv }\IeC {\cyri }\IeC {\cyrd } \IeC {\cyrp }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrl }\IeC {\cyro }\IeC {\cyrzh }\IeC {\cyre }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyrya }}{23}{subsubsection.3.1.6}%
\contentsline {section}{\cyrillictext \CYRZ \CYRA \CYRK \CYRL \CYRYU \CYRCH \CYRE \CYRN \CYRI \CYRE }{24}{section*.10}%
\contentsline {section}{\cyrillictext \CYRS \CYRP \CYRI \CYRS \CYRO \CYRK \ \CYRI \CYRS \CYRP \CYRO \CYRL \CYRSFTSN \CYRZ \CYRO \CYRV \CYRA \CYRN \CYRN \CYRERY \CYRH \ \CYRI \CYRS \CYRT \CYRO \CYRCH \CYRN \CYRI \CYRK \CYRO \CYRV }{25}{section*.11}%
\redeflsection
\ttl@change@i {\@ne }{section}{3ex}{\hspace {-3ex}}{\appendixname ~\thecontentslabel \hspace {2ex}}{\hspace {2.3em}}{\titlerule *[0.98ex]{.}\contentspage }\relax
\ttl@change@v {section}{}{}{}\relax
\contentsline {section}{\numberline {\CYRA }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } main.dart}{11}{appendix.A}%
\contentsline {section}{\numberline {\CYRB }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyrc }\IeC {\cyrery } \IeC {\cyro }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyri }}{12}{appendix.B}%
\contentsline {section}{\numberline {\CYRV }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyro }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyri } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyra }}{23}{appendix.C}%
\contentsline {section}{\numberline {\CYRG }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrk }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrs }\IeC {\cyra } \IeC {\cyrd }\IeC {\cyrl }\IeC {\cyrya } \IeC {\cyrr }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyrery } \IeC {\cyrs } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyro }\IeC {\cyrm }}{30}{appendix.D}%
\contentsline {section}{\numberline {\CYRA }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } main.dart}{26}{appendix.A}%
\contentsline {section}{\numberline {\CYRB }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrs }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrn }\IeC {\cyri }\IeC {\cyrc }\IeC {\cyrery } \IeC {\cyro }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyri }}{27}{appendix.B}%
\contentsline {section}{\numberline {\CYRV }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyro }\IeC {\cyrt }\IeC {\cyrr }\IeC {\cyri }\IeC {\cyrs }\IeC {\cyro }\IeC {\cyrv }\IeC {\cyrk }\IeC {\cyri } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyra }}{38}{appendix.C}%
\contentsline {section}{\numberline {\CYRG }\IeC {\CYRK }\IeC {\cyro }\IeC {\cyrd } \IeC {\cyrk }\IeC {\cyrl }\IeC {\cyra }\IeC {\cyrs }\IeC {\cyrs }\IeC {\cyra } \IeC {\cyrd }\IeC {\cyrl }\IeC {\cyrya } \IeC {\cyrr }\IeC {\cyra }\IeC {\cyrb }\IeC {\cyro }\IeC {\cyrt }\IeC {\cyrery } \IeC {\cyrs } \IeC {\cyrg }\IeC {\cyrr }\IeC {\cyra }\IeC {\cyrf }\IeC {\cyro }\IeC {\cyrm }}{45}{appendix.D}%
\contentsfinish

View File

@ -24,7 +24,6 @@ class _DrawingPageState extends State<DrawingPage> {
Graphs graphData = getGraph();
List<int?>? intListPath;
List<bool>? dfsAccessTable;
//List<int?>? dijkstraTable;
String op = Operations.none;
int? startDot;
int? endDot;

View File

@ -128,7 +128,6 @@ class CurvePainter extends CustomPainter {
print("GetDotPos error");
}
}
return off;
}
@ -245,7 +244,7 @@ class CurvePainter extends CustomPainter {
_drawDot(canvas, _off[start]!, 9, Colors.green);
_drawDot(canvas, _off[end]!, 7, Colors.red.shade200);
for (int i = 0; i < intListPath!.length; i++) {
_drawDotNum(canvas, _off[intListPath![i]]!, "bfs: ¹${i + 1}");
_drawDotNum(canvas, _off[intListPath![i]]!, "bfs: <EFBFBD>${i + 1}");
}
}
}

View File

@ -449,7 +449,7 @@ class Graphs {
result.sort((a, b) => a.l.compareTo(b.l));
return result;
}
//*****Getters*******
//******Print******
@ -541,7 +541,6 @@ class Graphs {
//************Àëãîðèòìû************
List<int>? bfsPath(int startDot, int goalDot) {
if (startDot == goalDot) return [startDot];
//if (!bfsHasPath(startDot, goalDot)) return null;
startDot--;
goalDot--;
List<List<int>>? graph = getLenTable();
@ -559,8 +558,7 @@ class Graphs {
q.add(startDot);
used[startDot] = true;
dst[startDot] = 0;
pr[startDot] =
-1; //Пометка, означающая, что у вершины startDot нет предыдущей.
pr[startDot] = -1; //у вершины нет предыдущей.
while (q.isNotEmpty) {
int cur = q.removeAt(0);
@ -578,21 +576,16 @@ class Graphs {
}
}
//Восстановим кратчайший путь
//Для восстановления пути пройдём его в обратном порядке, и развернём.
//Восстановление кратчайшиего путьи
List<int> path = <int>[];
int cur = goalDot; //текущая вершина пути
int cur = goalDot;
path.add(cur + 1);
while (pr[cur] != -1) {
//пока существует предыдущая вершина
cur = pr[cur]; //переходим в неё
path.add(cur + 1); //и дописываем к пути
cur = pr[cur];
path.add(cur + 1);
}
path = path.reversed.toList();
if (path[0] == (startDot + 1) &&
path[1] == (goalDot + 1) &&
!_dots[startDot].hasConnection(goalDot + 1)) return null;
@ -607,14 +600,12 @@ class Graphs {
}
List<int> stack = <int>[];
stack.add(v);
//pos.add(v);
while (stack.isNotEmpty) {
v = stack.removeLast();
if (!label[v]) {
label[v] = true;
for (int i in _dots[v].getL().keys) {
stack.add(i - 1);
//pos.add(i);
}
}
}
@ -630,7 +621,6 @@ class Graphs {
for (int i = 0; i < _amount; ++i) {
int v = -1;
for (int j = 0; j < _amount; ++j) {
// int t;
if (!u[j] && (v == -1 || d[j]! < d[v]!)) {
v = j;
}
@ -647,7 +637,6 @@ class Graphs {
}
}
for (int i = 0; i < d.length; i++) {
// подумать как убрать эту часть
if (d[i] == intMax) d[i] = null;
}
return d;

BIN
tex/pic/grafs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
tex/pic/result.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -61,4 +61,14 @@
note={URL:~\url{https://skia.org/docs/}(Äàòà îáðàùåíèÿ 20.11.2021). Çàãë. ñ ýêð. ßç. àíãë.},
}
@Manual{krusc,
title={Ìèíèìàëüíîå îñòîâíîå äåðåâî. Àëãîðèòì Êðóñêàëà. [{Ý}ëåêòðîííûé ðåñóðñ]},
note={URL:~\url{https://e-maxx.ru/algo/mst_kruskal}(Äàòà îáðàùåíèÿ 20.11.2021). Çàãë. ñ ýêð. ßç. ðóñ.},
}
@Manual{custompaint,
title={CustomPaint class. [{Ý}ëåêòðîííûé ðåñóðñ]},
note={URL:~\url{https://api.flutter.dev/flutter/widgets/CustomPaint-class.html}(Äàòà îáðàùåíèÿ 20.11.2021). Çàãë. ñ ýêð. ßç. àíãë.},
}
@Comment{jabref-meta: databaseType:bibtex;}