Merge pull request '[1] Лабораторная работа №1 "Структуры данных"' (#198) from stepushovgs/2026-rff_mp:stepushovgs into develop
Reviewed-on: #198
This commit is contained in:
commit
42999d4181
262
stepushovgs/.gitignore
vendored
Normal file
262
stepushovgs/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
# debug information files
|
||||||
|
*.dwo
|
||||||
|
|
||||||
|
#################################
|
||||||
|
############## Go ###############
|
||||||
|
#################################
|
||||||
|
|
||||||
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Code coverage profiles and other test artifacts
|
||||||
|
*.out
|
||||||
|
coverage.*
|
||||||
|
*.coverprofile
|
||||||
|
profile.cov
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
go.work.sum
|
||||||
|
|
||||||
|
# env file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Editor/IDE
|
||||||
|
# .idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
!go.mod
|
||||||
|
|
||||||
|
#################################
|
||||||
|
########### Obsidian ############
|
||||||
|
#################################
|
||||||
|
|
||||||
|
.obsidian/
|
||||||
BIN
stepushovgs/data-structures/docs/img/delete.pdf
Normal file
BIN
stepushovgs/data-structures/docs/img/delete.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/data-structures/docs/img/insert.pdf
Normal file
BIN
stepushovgs/data-structures/docs/img/insert.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/data-structures/docs/img/search.pdf
Normal file
BIN
stepushovgs/data-structures/docs/img/search.pdf
Normal file
Binary file not shown.
754
stepushovgs/data-structures/docs/src/main.ipynb
Normal file
754
stepushovgs/data-structures/docs/src/main.ipynb
Normal file
File diff suppressed because one or more lines are too long
122
stepushovgs/data-structures/docs/Отчёт.md
Normal file
122
stepushovgs/data-structures/docs/Отчёт.md
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
## Практические графики
|
||||||
|
### Информация о тестировании
|
||||||
|
- Общее число записей: 20000
|
||||||
|
- Каждый замер повторялся: 20 раз
|
||||||
|
- Количество существующих записей для случайного поиска: 1000
|
||||||
|
- Количество несуществующих записей для поиска: 500
|
||||||
|
- Количество элементов для удаления: 1000
|
||||||
|
|
||||||
|
![[insert.pdf]]
|
||||||
|
**Тестирование вставки (рис. 1)**
|
||||||
|
|
||||||
|
![[search.pdf]]
|
||||||
|
**Тестирование поиска (рис. 2)**
|
||||||
|
|
||||||
|
![[delete.pdf]]
|
||||||
|
**Тестирование удаления (рис. 3)**
|
||||||
|
## Анализ результатов
|
||||||
|
|
||||||
|
### Как порядок входных данных влияет на скорость вставки в BST (деградация до O(n) на отсортированных данных)?
|
||||||
|
|
||||||
|
По определению, при вставке отсортированных данных, структура бинарного дерева поиска вырождается в связный список.
|
||||||
|
Для визуализации этого в тесте выводятся высота и количество элементов в дереве:
|
||||||
|
Для случайных данных вывод выглядит примерно так:
|
||||||
|
```
|
||||||
|
Высота дерева: 28, элементов: 8634
|
||||||
|
```
|
||||||
|
Для сортированных данных же:
|
||||||
|
```
|
||||||
|
Высота дерева: 8634, элементов: 8634
|
||||||
|
```
|
||||||
|
Заметим, что при случайных данных скорость вставки в бинарное дерево почти лишь немного уступает по скорости хеш-таблице. При сортированных данных из-за рекурсивной реализации вставки бинарное дерево проигрывает связному списку(который имеет линейную сложность вставки)
|
||||||
|
|
||||||
|
### Почему хеш-таблица почти не чувствительна к порядку.
|
||||||
|
Хеш-таблица не чувствительна к порядку данных, так как использует для распределения элементов хеш значения данных (сложность операции одинакова для любых однотипных данных) и после производит вставку в связный список(в моей реализации проходит по списку и вставляет данные в конец). Поэтому хеш-таблица ни на одном из этапов не сравнивает данные, следовательно их порядок не влияет на скорость.
|
||||||
|
|
||||||
|
### Почему связный список всегда медленен при поиске.
|
||||||
|
Операция поиска в связном списке имеет линейную сложность $O(n)$ не зависимо от порядка данных, что можно видеть на графике (см. рис. 2). Для бинарного дерева поиска эта сложность в лучшем случае $O(\log(N))$, а в худшем $O(N)$. Для хеш-таблицы сложность вставки $O(1)$, с хорошей хеш-функцией и низким заполнением.
|
||||||
|
|
||||||
|
### Как удаление работает в каждой структуре.
|
||||||
|
#### Связный список
|
||||||
|
Находим элемент перед удаляем элементом, и заменяем его поле `next` на `next.next`, то есть теперь он указывает на элемент, который идёт после удаляемого элемента:
|
||||||
|
``` Go
|
||||||
|
current := ll.head
|
||||||
|
|
||||||
|
for current.next != nil {
|
||||||
|
if current.next.data.Name == targetName {
|
||||||
|
current.next = current.next.next
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Бинарное дерево поиска
|
||||||
|
После того, как мы нашли узел, который необходимо удалить, у нас возможны три случая.
|
||||||
|
|
||||||
|
Случай 1: У удаляемого узла нет правого ребенка.
|
||||||
|
В этом случае мы просто перемещаем левого ребенка (3) на место удаляемого узла(5). В результате дерево будет выглядеть так:
|
||||||
|
```
|
||||||
|
Удаляем элемент со значением 5
|
||||||
|
ДО УДАЛЕНИЯ: ПОСЛЕ УДАЛЕНИЯ:
|
||||||
|
|
||||||
|
[8] [8]
|
||||||
|
/ \ / \
|
||||||
|
[5] [10] [3] [10]
|
||||||
|
/ / \
|
||||||
|
[3] [1] [4]
|
||||||
|
/ \
|
||||||
|
[1] [4]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Случай 2: У удаляемого узла есть только правый ребенок, у которого, в свою очередь нет левого ребенка.
|
||||||
|
В этом случае нам надо переместить правого ребенка(8) удаляемого узла (5) на его место.
|
||||||
|
```
|
||||||
|
Удаляем элемент со значением 5
|
||||||
|
До удаления: После удаления:
|
||||||
|
|
||||||
|
[10] [10]
|
||||||
|
/ \ / \
|
||||||
|
[5] [12] [8] [12]
|
||||||
|
/ \ / \
|
||||||
|
[1] [8] [1] [9]
|
||||||
|
\
|
||||||
|
[9]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Случай 3: У удаляемого узла есть первый ребенок, у которого есть левый ребенок.
|
||||||
|
В этом случае место удаляемого узла занимает крайний левый ребенок правого ребенка удаляемого узла.
|
||||||
|
Давайте посмотрим, почему это так. Мы знаем о поддереве, начинающемся с удаляемого узла следующее:
|
||||||
|
|
||||||
|
- Все значения справа от него больше или равны значению самого узла.
|
||||||
|
- Наименьшее значение правого поддерева — крайнее левое.
|
||||||
|
|
||||||
|
Мы должны поместить на место удаляемого узел со значением, меньшим или равным любому узлу справа от него. Для этого нам необходимо найти наименьшее значение в правом поддереве. Поэтому мы берем крайний левый узел правого поддерева.
|
||||||
|
|
||||||
|
```
|
||||||
|
Удаляем элемент со значением 5
|
||||||
|
До удаления: После удаления:
|
||||||
|
|
||||||
|
[10] [10]
|
||||||
|
/ \ / \
|
||||||
|
[5] [12] [7] [12]
|
||||||
|
/ \ / \
|
||||||
|
[1] [9] [1] [9]
|
||||||
|
/ /
|
||||||
|
[7] [8]
|
||||||
|
\
|
||||||
|
[8]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Хеш-таблица
|
||||||
|
Находим индекс элемента в таблица, далее производим удаление элемента в связном списке, который соответствует этому индексу.
|
||||||
|
|
||||||
|
|
||||||
|
# Вывод
|
||||||
|
Мы реализовали и протестировали три различные структуры хранения данных: связный список, бинарное дерево поиска и хеш-таблица. Сравнили скорость операций вставки, удаления и поиска для каждой структуры.
|
||||||
|
Если не важен порядок хранения и извлечения данных, то хеш-таблица лучший выбор для быстрых вставки, удаления и поиска.
|
||||||
|
Если нужно хранить данные с возможностью быстрого отсортированного обхода, то стоит выбрать бинарное дерево поиска.
|
||||||
|
Если нужно хранить данные в порядке поступления(например очередь), то стоит выбрать связный список.
|
||||||
|
|
||||||
208
stepushovgs/data-structures/source/bin_search_tree_C/bst.c
Normal file
208
stepushovgs/data-structures/source/bin_search_tree_C/bst.c
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bst.h"
|
||||||
|
#include "queue.h"
|
||||||
|
/*
|
||||||
|
3. Двоичное дерево поиска
|
||||||
|
Узел — словарь: `{'val': '123', 'left': None, 'right': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def bst_insert(root, name, phone) — рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется).
|
||||||
|
|
||||||
|
def bst_find(root, name) — поиск.
|
||||||
|
|
||||||
|
def bst_delete(root, name) — удаление, возвращает новый корень.
|
||||||
|
|
||||||
|
def bst_list_all(root) — центрированный обход (рекурсивно собирает записи в отсортированном порядке).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bst_node* create_bst_node(char name[NAME_LEN], char phone[PHONE_LEN])
|
||||||
|
{
|
||||||
|
bst_node* node = (bst_node*)malloc(sizeof(bst_node));
|
||||||
|
|
||||||
|
strcpy(node->name, name);
|
||||||
|
strcpy(node->phone, phone);
|
||||||
|
|
||||||
|
node->left = NULL;
|
||||||
|
node->right = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_minimum(bst_node* node)
|
||||||
|
{
|
||||||
|
if (node->left == NULL)
|
||||||
|
return node;
|
||||||
|
return bst_minimum(node->left);
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_maximum(bst_node* node)
|
||||||
|
{
|
||||||
|
if (node->right == NULL)
|
||||||
|
return node;
|
||||||
|
return bst_maximum(node->right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_bst(bst_node node)
|
||||||
|
{
|
||||||
|
//printf("value: %d\n", node.value);
|
||||||
|
|
||||||
|
printf("name: %s, phone: %s\n", node.name, node.phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bst_inorder_traversal(bst_node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD != NULL)
|
||||||
|
{
|
||||||
|
bst_inorder_traversal(HEAD->left);
|
||||||
|
print_bst(*HEAD);
|
||||||
|
bst_inorder_traversal(HEAD->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bst_preorder_traversal(bst_node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD != NULL)
|
||||||
|
{
|
||||||
|
print_bst(*HEAD);
|
||||||
|
bst_preorder_traversal(HEAD->left);
|
||||||
|
bst_preorder_traversal(HEAD->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_search(bst_node* HEAD, char target_name[NAME_LEN])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Node search(x : Node, k : T):
|
||||||
|
if x == null or k == x.key
|
||||||
|
return x
|
||||||
|
if k < x.key
|
||||||
|
return search(x.left, k)
|
||||||
|
else
|
||||||
|
return search(x.right, k)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((HEAD == NULL) || strcmp(HEAD->name, target_name) == 0)
|
||||||
|
{
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
if (strcmp(target_name, HEAD->name) < 0)
|
||||||
|
{
|
||||||
|
return bst_search(HEAD->left, target_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return bst_search(HEAD->right, target_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_insert(bst_node* HEAD, char name[NAME_LEN], char phone[PHONE_LEN])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Node insert(x : Node, z : T): // x — корень поддерева, z — вставляемый ключ
|
||||||
|
if x == null
|
||||||
|
return Node(z) // подвесим Node с key = z
|
||||||
|
else if z < x.key
|
||||||
|
x.left = insert(x.left, z)
|
||||||
|
else if z > x.key
|
||||||
|
x.right = insert(x.right, z)
|
||||||
|
return x
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (HEAD == NULL)
|
||||||
|
{
|
||||||
|
return create_bst_node(name, phone);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, HEAD->name) < 0)
|
||||||
|
{
|
||||||
|
HEAD->left = bst_insert(HEAD->left, name, phone);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, HEAD->name) > 0)
|
||||||
|
{
|
||||||
|
HEAD->right = bst_insert(HEAD->right, name, phone);
|
||||||
|
}
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_delete(bst_node* root, char target_name[NAME_LEN])
|
||||||
|
{ // корень поддерева, удаляемый ключ
|
||||||
|
if (root == NULL)
|
||||||
|
return root;
|
||||||
|
|
||||||
|
if (strcmp(target_name, root->name) < 0)
|
||||||
|
root->left = bst_delete(root->left, target_name);
|
||||||
|
else if (strcmp(target_name, root->name) > 0)
|
||||||
|
root->right = bst_delete(root->right, target_name);
|
||||||
|
else {
|
||||||
|
if (root->left != NULL && root->right != NULL)
|
||||||
|
{
|
||||||
|
strcpy(root->name, bst_minimum(root->right)->name);
|
||||||
|
strcpy(root->phone, bst_minimum(root->right)->phone);
|
||||||
|
|
||||||
|
root->right = bst_delete(root->right, root->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bst_node* temp = root;
|
||||||
|
if (root->left != NULL)
|
||||||
|
root = root->left;
|
||||||
|
else
|
||||||
|
root = root->right;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_bst(bst_node* root)
|
||||||
|
{
|
||||||
|
if (root == NULL)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete_bst(root->left);
|
||||||
|
delete_bst(root->right);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTree(bst_node* node, int depth) {
|
||||||
|
|
||||||
|
if (node == NULL) return;
|
||||||
|
|
||||||
|
printTree(node->right, depth + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
printf("\t");
|
||||||
|
//printf("%d\n", node->value);
|
||||||
|
print_bst(*node);
|
||||||
|
|
||||||
|
printTree(node->left, depth + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void treeLevelTraversal(bst_node* node) {
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
Queue q;
|
||||||
|
Queue* hq = &q;
|
||||||
|
queueInit(hq);
|
||||||
|
|
||||||
|
queuePush(hq, node);
|
||||||
|
while(!queueEmpty(hq))
|
||||||
|
{
|
||||||
|
bst_node* hn = queuePop(hq);
|
||||||
|
//printf("%d\n", hn->value);
|
||||||
|
print_bst(*hn);
|
||||||
|
|
||||||
|
if(hn->left)
|
||||||
|
queuePush(hq, hn->left);
|
||||||
|
if(hn->right)
|
||||||
|
queuePush(hq, hn->right);
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
37
stepushovgs/data-structures/source/bin_search_tree_C/bst.h
Normal file
37
stepushovgs/data-structures/source/bin_search_tree_C/bst.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#define NAME_LEN 20
|
||||||
|
#define PHONE_LEN 20
|
||||||
|
|
||||||
|
typedef struct bst_node
|
||||||
|
{
|
||||||
|
//int value;
|
||||||
|
|
||||||
|
char name[NAME_LEN];
|
||||||
|
char phone[PHONE_LEN];
|
||||||
|
|
||||||
|
struct bst_node* right;
|
||||||
|
struct bst_node* left;
|
||||||
|
}bst_node;
|
||||||
|
|
||||||
|
bst_node* create_bst_node(char name[NAME_LEN], char phone[PHONE_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_minimum(bst_node* node);
|
||||||
|
|
||||||
|
bst_node* bst_maximum(bst_node* node);
|
||||||
|
|
||||||
|
void print_bst(bst_node node);
|
||||||
|
|
||||||
|
void bst_inorder_traversal(bst_node* HEAD);
|
||||||
|
|
||||||
|
void bst_preorder_traversal(bst_node* HEAD);
|
||||||
|
|
||||||
|
bst_node* bst_search(bst_node* HEAD, char target_name[NAME_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_insert(bst_node* HEAD, char name[NAME_LEN], char phone[PHONE_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_delete(bst_node* root, char target_name[NAME_LEN]);
|
||||||
|
|
||||||
|
void treeLevelTraversal(bst_node* node);
|
||||||
|
|
||||||
|
void printTree(bst_node* node, int depth);
|
||||||
|
|
||||||
|
void delete_bst(bst_node* root);
|
||||||
42
stepushovgs/data-structures/source/bin_search_tree_C/queue.c
Normal file
42
stepushovgs/data-structures/source/bin_search_tree_C/queue.c
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
int queueEmpty(Queue* q)
|
||||||
|
{
|
||||||
|
return (q->head == q->tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size(Queue* q)
|
||||||
|
{
|
||||||
|
if (q->head > q->tail)
|
||||||
|
return QUEUE_MAX_LENGTH - q->head + q->tail;
|
||||||
|
else
|
||||||
|
return q->tail - q->head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queuePush(Queue* q, void* ptr)
|
||||||
|
{
|
||||||
|
if (size(q) != QUEUE_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
q->p[q->tail] = ptr;
|
||||||
|
q->tail = (q->tail + 1) % QUEUE_MAX_LENGTH;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void queueInit(Queue* q)
|
||||||
|
{
|
||||||
|
q->head = 0;
|
||||||
|
q->tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* queuePop(Queue* q)
|
||||||
|
{
|
||||||
|
if (queueEmpty(q))
|
||||||
|
return NULL;
|
||||||
|
void* x = q->p[q->head];
|
||||||
|
q->head = (q->head + 1) % QUEUE_MAX_LENGTH;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
17
stepushovgs/data-structures/source/bin_search_tree_C/queue.h
Normal file
17
stepushovgs/data-structures/source/bin_search_tree_C/queue.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#define QUEUE_MAX_LENGTH 100
|
||||||
|
|
||||||
|
typedef struct Queue {
|
||||||
|
void* p[QUEUE_MAX_LENGTH];
|
||||||
|
unsigned int head;
|
||||||
|
unsigned int tail;
|
||||||
|
} Queue;
|
||||||
|
|
||||||
|
int queueEmpty(Queue* q);
|
||||||
|
|
||||||
|
void queuePush(Queue* q, void* p);
|
||||||
|
|
||||||
|
void* queuePop(Queue* q);
|
||||||
|
|
||||||
|
void queueInit(Queue* q);
|
||||||
|
|
||||||
|
int size(Queue* q);
|
||||||
3
stepushovgs/data-structures/source/go.mod
Normal file
3
stepushovgs/data-structures/source/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module source
|
||||||
|
|
||||||
|
go 1.26.3
|
||||||
166
stepushovgs/data-structures/source/linked_list_c/linked_list.c
Normal file
166
stepushovgs/data-structures/source/linked_list_c/linked_list.c
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Связный список (LinkedListPhoneBook)
|
||||||
|
|
||||||
|
Узел представляется словарём: `{'name': 'Имя', 'phone': '123', 'next': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def ll_insert(head, name, phone) — проходит до конца (или сразу добавляет в конец) и возвращает новую голову (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||||
|
|
||||||
|
def ll_find(head, name) — ищет узел, возвращает телефон или None.
|
||||||
|
|
||||||
|
def ll_delete(head, name) — удаляет узел, возвращает новую голову.
|
||||||
|
|
||||||
|
def ll_list_all(head) — собирает все записи в список и сортирует (сортировка вынесена отдельно).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int getListNodeLength(Node* HEAD)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
Node* current = HEAD;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавление в конец
|
||||||
|
Node* insert(Node* head, char name[NAME_BUFF_SIZE], char phone[PHONE_BUFF_SIZE], int show)
|
||||||
|
{
|
||||||
|
Node* newNode = (Node*)malloc(sizeof(Node));
|
||||||
|
|
||||||
|
strcpy_s(newNode->name_, NAME_BUFF_SIZE, name);
|
||||||
|
strcpy_s(newNode->phone_, PHONE_BUFF_SIZE, phone);
|
||||||
|
newNode->next = NULL;
|
||||||
|
|
||||||
|
printf("Data: %s %s\n", name, phone);
|
||||||
|
printf("New Data: %s %s\n", newNode->name_, newNode->phone_);
|
||||||
|
|
||||||
|
if (head == NULL)
|
||||||
|
{
|
||||||
|
printf("\nNew list\n");
|
||||||
|
head = newNode;
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* last = head;
|
||||||
|
int ind = 0;
|
||||||
|
while (last->next != NULL)
|
||||||
|
{
|
||||||
|
if (show == 1)
|
||||||
|
printf("%d \n", ind++);
|
||||||
|
last = last->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
last->next = newNode;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* find(Node* HEAD, char target_name[NAME_BUFF_SIZE])
|
||||||
|
{
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
return current->phone_;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вывод всех элементов
|
||||||
|
void printAllNodes(Node* head)
|
||||||
|
{
|
||||||
|
Node* current = head;
|
||||||
|
int ind = 0;
|
||||||
|
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
printf("Ind: %d\nName: %s\nPhone: %s\n", ind++, current->name_, current->phone_);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* deleteNode(Node* HEAD, char target_name[NAME_BUFF_SIZE])
|
||||||
|
{
|
||||||
|
Node* previous = NULL;
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
if (current != NULL && strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
HEAD = current->next;
|
||||||
|
free(current);
|
||||||
|
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (current != NULL && strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == NULL) return HEAD;
|
||||||
|
|
||||||
|
previous->next = current->next;
|
||||||
|
free(current);
|
||||||
|
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* listAll(Node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = getListNodeLength(HEAD);
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
Node* list = (Node*)malloc(len * sizeof(Node));
|
||||||
|
|
||||||
|
int ind = 0;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
list[ind++] = *current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printNode(Node node)
|
||||||
|
{
|
||||||
|
printf("%s ", node.name_);
|
||||||
|
printf("%s\n", node.phone_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printListNode(Node* list, int length)
|
||||||
|
{
|
||||||
|
printf("\n\n%d\n", length);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
printNode(list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#define NAME_BUFF_SIZE 50
|
||||||
|
#define PHONE_BUFF_SIZE 12+1 // +1 for end symbol
|
||||||
|
|
||||||
|
typedef struct Node
|
||||||
|
{
|
||||||
|
char name_[NAME_BUFF_SIZE];
|
||||||
|
char phone_[PHONE_BUFF_SIZE];
|
||||||
|
struct Node* next;
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
typedef struct LinkedListPhoneNumbers {
|
||||||
|
Node* HEAD;
|
||||||
|
} LinkedListPhoneNumbers;
|
||||||
|
|
||||||
|
Node* insert(Node* head, char name[NAME_BUFF_SIZE], char phone[PHONE_BUFF_SIZE], int show);
|
||||||
|
void printAllNodes(Node* head);
|
||||||
|
void printNode(Node node);
|
||||||
|
|
||||||
|
char* find(Node* HEAD, char target_name[NAME_BUFF_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
|
Node* deleteNode(Node* HEAD, char target_name[NAME_BUFF_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
|
Node* listAll(Node* HEAD);
|
||||||
|
|
||||||
|
void printListNode(Node list[], int length);
|
||||||
|
|
||||||
|
int getListNodeLength(Node* HEAD);
|
||||||
44
stepushovgs/data-structures/source/old_c/main.c
Normal file
44
stepushovgs/data-structures/source/old_c/main.c
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "linked_list/linked_list.h"
|
||||||
|
|
||||||
|
#define NAME_BUFF_SIZE 50
|
||||||
|
#define PHONE_BUFF_SIZE 12+1 // +1 for end symbol
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Node* list = NULL;
|
||||||
|
char phone[] = "1234";
|
||||||
|
for (int i = 0; i < 12; i++)
|
||||||
|
{
|
||||||
|
char num[3];
|
||||||
|
sprintf_s(num, 3, "%d", i);
|
||||||
|
|
||||||
|
char name[] = "name ";
|
||||||
|
strcat_s(name, 9, num);
|
||||||
|
printf("%d %s %s\n", i, name, phone);
|
||||||
|
list = insert(list, name, phone, 0);
|
||||||
|
}
|
||||||
|
char test_name[] = "name 20";
|
||||||
|
char test_phone[] = "phone 343";
|
||||||
|
|
||||||
|
list = insert(list, test_name, test_phone, 1);
|
||||||
|
|
||||||
|
printAllNodes(list);
|
||||||
|
|
||||||
|
printf("\n%s\n", find(list, test_name));
|
||||||
|
|
||||||
|
strcpy_s(test_name, NAME_BUFF_SIZE, "name 10");
|
||||||
|
list = deleteNode(list, test_name);
|
||||||
|
|
||||||
|
printAllNodes(list);
|
||||||
|
|
||||||
|
Node* listNodes = listAll(list);
|
||||||
|
printListNode(listNodes, getListNodeLength(list));
|
||||||
|
|
||||||
|
free(listNodes);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
86
stepushovgs/data-structures/source/old_c/main_tree.c
Normal file
86
stepushovgs/data-structures/source/old_c/main_tree.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bin_search_tree/bst.h"
|
||||||
|
|
||||||
|
#define COUNT_NUMBERS 64
|
||||||
|
|
||||||
|
int isInArr(int arr[], int len, int target)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (arr[i] == target) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_dozen(int number)
|
||||||
|
{
|
||||||
|
return (char)'0' + number % 10;
|
||||||
|
}
|
||||||
|
char get_units(int number)
|
||||||
|
{
|
||||||
|
return (char)'0' + number / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("hello world!\n");
|
||||||
|
|
||||||
|
//bst_node* head = create_bst_node("name", "phone");
|
||||||
|
bst_node* head = NULL;
|
||||||
|
|
||||||
|
int arr[COUNT_NUMBERS] = {0};
|
||||||
|
char name[NAME_LEN] = "name_xx";
|
||||||
|
char phone[PHONE_LEN] = "phone_xx";
|
||||||
|
int temp = 0;
|
||||||
|
for (int i = 0; i < COUNT_NUMBERS; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp = rand() % 100;
|
||||||
|
}
|
||||||
|
while (isInArr(arr, i - 1, temp));
|
||||||
|
|
||||||
|
arr[i] = temp;
|
||||||
|
|
||||||
|
name[5] = get_dozen(temp);
|
||||||
|
name[6] = get_units(temp);
|
||||||
|
|
||||||
|
phone[6] = get_dozen(temp);
|
||||||
|
phone[7] = get_units(temp);
|
||||||
|
|
||||||
|
|
||||||
|
head = bst_insert(head, name, phone);
|
||||||
|
printf("%d ", arr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\ninorder traversal: \n");
|
||||||
|
bst_inorder_traversal(head);
|
||||||
|
|
||||||
|
printf("\n\npreorder traversal: \n");
|
||||||
|
bst_preorder_traversal(head);
|
||||||
|
|
||||||
|
char tar_name[NAME_LEN] = "name_44";
|
||||||
|
|
||||||
|
printf("\n\nУдаляем элемент с значением %s:\n", tar_name);
|
||||||
|
|
||||||
|
head = bst_delete(head, tar_name);
|
||||||
|
|
||||||
|
bst_inorder_traversal(head);
|
||||||
|
|
||||||
|
|
||||||
|
printf("\n\nВывод дерева:\n");
|
||||||
|
|
||||||
|
printTree(head, 0);
|
||||||
|
|
||||||
|
printf("\n\nОбход в ширину:\n");
|
||||||
|
treeLevelTraversal(head);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
delete_bst(head);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
40
stepushovgs/data-structures/source/old_c/swap.c
Normal file
40
stepushovgs/data-structures/source/old_c/swap.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int Partition_Hoa(int arr[], int l, int r)
|
||||||
|
{
|
||||||
|
int p = arr[(l + r) / 2];
|
||||||
|
int i = l;
|
||||||
|
int j = r;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// #print(p)
|
||||||
|
while (arr[i] <= p) i++;
|
||||||
|
while (arr[j] > p) j--;
|
||||||
|
|
||||||
|
if (i >= j) return j;
|
||||||
|
|
||||||
|
swap(arr[i], arr[j]);
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void QuickSort(int arr[], int l, int r)
|
||||||
|
{
|
||||||
|
if (l < r):
|
||||||
|
{
|
||||||
|
int s = Partition_Hoa(arr, l, r);
|
||||||
|
QuickSort(arr, l, s-1);
|
||||||
|
QuickSort(arr, s+1, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int arr[] = {2, 56, 10, 5, 2, 6, 9, 6, 3, 923, 3, 2, 1};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package csvwriter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BenchmarkResult struct {
|
||||||
|
Structure string
|
||||||
|
Mode string
|
||||||
|
Operation string
|
||||||
|
Time float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BenchmarkResult) ToString() string {
|
||||||
|
return fmt.Sprintf("%s %s %s %f", b.Structure, b.Mode, b.Operation, b.Time)
|
||||||
|
}
|
||||||
|
func (b *BenchmarkResult) ToStrings() []string {
|
||||||
|
return []string{b.Structure, b.Mode, b.Operation, fmt.Sprintf("%f", b.Time)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаём пустой csv файл с заголовками
|
||||||
|
func CreateEmptyCSV(dir, name string) error {
|
||||||
|
filename := filepath.Join(dir, name)
|
||||||
|
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
writer := csv.NewWriter(file)
|
||||||
|
defer writer.Flush()
|
||||||
|
header := []string{"Structure", "Mode", "Operation", "Time"}
|
||||||
|
writer.Write(header)
|
||||||
|
|
||||||
|
return writer.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendRaw дописывает произвольные строки в CSV
|
||||||
|
func AppendRaw(results []BenchmarkResult) error {
|
||||||
|
|
||||||
|
filename := filepath.Join("results", "benchmarks.csv")
|
||||||
|
|
||||||
|
fileExists := true
|
||||||
|
isEmpty := true
|
||||||
|
if info, err := os.Stat(filename); err == nil {
|
||||||
|
isEmpty = info.Size() == 0
|
||||||
|
} else if os.IsNotExist(err) {
|
||||||
|
fileExists = false
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
writer := csv.NewWriter(file)
|
||||||
|
defer writer.Flush()
|
||||||
|
|
||||||
|
// Если файл новый или пустой, записываем заголовки
|
||||||
|
if !fileExists || isEmpty {
|
||||||
|
header := []string{"Structure", "Mode", "Operation", "Time"}
|
||||||
|
if err := writer.Write(header); err != nil {
|
||||||
|
return fmt.Errorf("не удалось записать заголовки: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := make([][]string, len(results))
|
||||||
|
|
||||||
|
for i, res := range results {
|
||||||
|
rows[i] = res.ToStrings()
|
||||||
|
// fmt.Println(res.ToStrings())
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer.WriteAll(rows) // WriteAll пишет всё сразу
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package data_struct
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type MyData struct {
|
||||||
|
Name string
|
||||||
|
Phone string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewData(name, phone string) *MyData {
|
||||||
|
return &MyData{
|
||||||
|
Name: name,
|
||||||
|
Phone: phone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *MyData) ToString() string {
|
||||||
|
return fmt.Sprintf("Имя: %s, Телефон: %s", d.Name, d.Phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintList(list []MyData) {
|
||||||
|
for _, el := range list {
|
||||||
|
fmt.Printf("%s\n", el.ToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
44
stepushovgs/data-structures/source/pkg/data_struct/qsort.go
Normal file
44
stepushovgs/data-structures/source/pkg/data_struct/qsort.go
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
package data_struct
|
||||||
|
|
||||||
|
func QSort(arr []MyData, l, r int) []MyData {
|
||||||
|
result := make([]MyData, len(arr))
|
||||||
|
copy(result, arr)
|
||||||
|
qSort(result, l, r)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func qSort(arr []MyData, l, r int) []MyData {
|
||||||
|
if l < r {
|
||||||
|
s := Partition_Hoa(arr, l, r)
|
||||||
|
arr = qSort(arr, l, s)
|
||||||
|
arr = qSort(arr, s+1, r)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
func Partition_Hoa(arr []MyData, l, r int) int {
|
||||||
|
p := arr[(l+r)/2].Name
|
||||||
|
i := l - 1
|
||||||
|
j := r + 1
|
||||||
|
|
||||||
|
for {
|
||||||
|
for {
|
||||||
|
i++
|
||||||
|
if arr[i].Name >= p {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
j--
|
||||||
|
if arr[j].Name <= p {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= j {
|
||||||
|
return j
|
||||||
|
}
|
||||||
|
|
||||||
|
arr[i], arr[j] = arr[j], arr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package gen_data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAX_USER_IND = 10000
|
||||||
|
PHONE_LEN = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
func genRandomPhone() string {
|
||||||
|
phone := ""
|
||||||
|
for i := 0; i < PHONE_LEN; i++ {
|
||||||
|
phone += fmt.Sprintf("%d", rand.Intn(10))
|
||||||
|
}
|
||||||
|
|
||||||
|
return phone
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecordsShuffled(count int) []ds.MyData {
|
||||||
|
data := make([]ds.MyData, count)
|
||||||
|
number := 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
number = rand.Intn(MAX_USER_IND)
|
||||||
|
data[i].Name = fmt.Sprintf("User_%05d", number)
|
||||||
|
data[i].Phone = genRandomPhone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Перемешиваем (Fisher-Yates shuffle)
|
||||||
|
for i := len(data) - 1; i > 0; i-- {
|
||||||
|
j := rand.Intn(i + 1)
|
||||||
|
data[i], data[j] = data[j], data[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecordsSorted(count int) []ds.MyData {
|
||||||
|
data := RecordsShuffled(count)
|
||||||
|
|
||||||
|
data = ds.QSort(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,287 @@
|
||||||
|
package bin_search_tree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BinSearchTree struct {
|
||||||
|
root *BSTree
|
||||||
|
}
|
||||||
|
|
||||||
|
type BSTree struct {
|
||||||
|
data ds.MyData
|
||||||
|
|
||||||
|
left *BSTree
|
||||||
|
right *BSTree
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBinSearchTree() *BinSearchTree {
|
||||||
|
return &BinSearchTree{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBinSearchTree(data ds.MyData) *BSTree {
|
||||||
|
return &BSTree{
|
||||||
|
data: data,
|
||||||
|
left: nil,
|
||||||
|
right: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Len() int {
|
||||||
|
return bst.root.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BSTree) Len() int {
|
||||||
|
if bst == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1 + bst.left.Len() + bst.right.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Minimum() *BSTree {
|
||||||
|
return bst.root.Minimum()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *BSTree) Minimum() *BSTree {
|
||||||
|
if root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if root.left == nil {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
return root.left.Minimum()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Maximum() *BSTree {
|
||||||
|
return bst.root.Maximum()
|
||||||
|
}
|
||||||
|
func (root *BSTree) Maximum() *BSTree {
|
||||||
|
if root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if root.right == nil {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
return root.right.Maximum()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *BSTree) PrintNode() {
|
||||||
|
fmt.Print(node.data.ToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *BSTree) ToString() string {
|
||||||
|
if node == nil {
|
||||||
|
return "nil"
|
||||||
|
}
|
||||||
|
return node.data.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) BstInorderTraversal() {
|
||||||
|
bst.root.BstInorderTraversal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *BSTree) BstInorderTraversal() {
|
||||||
|
if root != nil {
|
||||||
|
root.left.BstInorderTraversal()
|
||||||
|
root.PrintNode()
|
||||||
|
fmt.Println()
|
||||||
|
root.right.BstInorderTraversal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) BstPreorderTraversal() {
|
||||||
|
bst.root.BstPreorderTraversal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *BSTree) BstPreorderTraversal() {
|
||||||
|
if root != nil {
|
||||||
|
root.PrintNode()
|
||||||
|
fmt.Println()
|
||||||
|
root.left.BstPreorderTraversal()
|
||||||
|
root.right.BstPreorderTraversal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
// Возвращает номер телефона по имени
|
||||||
|
func (bst *BinSearchTree) Search(targetName string) (string, bool) {
|
||||||
|
node, ok := bst.root.search(targetName)
|
||||||
|
if ok {
|
||||||
|
return node.data.Phone, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Node search(x : Node, k : T):
|
||||||
|
if x == null or k == x.key
|
||||||
|
return x
|
||||||
|
if k < x.key
|
||||||
|
return search(x.left, k)
|
||||||
|
else
|
||||||
|
return search(x.right, k)
|
||||||
|
*/
|
||||||
|
// Приватная вспомогательная функция поиска
|
||||||
|
func (node *BSTree) search(targetName string) (*BSTree, bool) {
|
||||||
|
if node == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if node.data.Name == targetName {
|
||||||
|
return node, true
|
||||||
|
}
|
||||||
|
if targetName < node.data.Name {
|
||||||
|
return node.left.search(targetName)
|
||||||
|
}
|
||||||
|
return node.right.search(targetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (node *BinSearchTree) Insert(data ds.MyData) *BinSearchTree {
|
||||||
|
// if node == nil {
|
||||||
|
// return NewBinSearchTree(data)
|
||||||
|
// } else if data.Name < node.data.Name {
|
||||||
|
// node.left = node.left.Insert(data)
|
||||||
|
// } else if data.Name > node.data.Name {
|
||||||
|
// node.right = node.right.Insert(data)
|
||||||
|
// } else {
|
||||||
|
// node.data.Phone = data.Phone // Заменяем существующее значение
|
||||||
|
// }
|
||||||
|
// return node
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Insert(data ds.MyData) {
|
||||||
|
bst.root = bst.root.insert(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *BSTree) insert(data ds.MyData) *BSTree {
|
||||||
|
if root == nil {
|
||||||
|
return &BSTree{
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Name < root.data.Name {
|
||||||
|
root.left = root.left.insert(data)
|
||||||
|
} else if data.Name > root.data.Name {
|
||||||
|
root.right = root.right.insert(data)
|
||||||
|
} else {
|
||||||
|
root.data.Phone = data.Phone
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) InsertAll(data []ds.MyData) {
|
||||||
|
for _, el := range data {
|
||||||
|
bst.Insert(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete удаляет узел по имени.
|
||||||
|
// Возвращает нового потомка для родительского узла.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Node delete(root : Node, z : T): // корень поддерева, удаляемый ключ
|
||||||
|
if root == null
|
||||||
|
return root
|
||||||
|
if z < root.key
|
||||||
|
root.left = delete(root.left, z)
|
||||||
|
else if z > root.key
|
||||||
|
root.right = delete(root.right, z)
|
||||||
|
else if root.left != null and root.right != null
|
||||||
|
root.key = minimum(root.right).key
|
||||||
|
root.right = delete(root.right, root.key)
|
||||||
|
else
|
||||||
|
if root.left != null
|
||||||
|
root = root.left
|
||||||
|
else if root.right != null
|
||||||
|
root = root.right
|
||||||
|
else
|
||||||
|
root = null
|
||||||
|
return root
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Height() int {
|
||||||
|
if bst.root == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return bst.root.height()
|
||||||
|
}
|
||||||
|
|
||||||
|
// height возвращает высоту поддерева (для BSTree)
|
||||||
|
func (node *BSTree) height() int {
|
||||||
|
if node == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
leftHeight := node.left.height()
|
||||||
|
rightHeight := node.right.height()
|
||||||
|
|
||||||
|
// Высота = 1 (текущий узел) + максимум из высот поддеревьев
|
||||||
|
if leftHeight > rightHeight {
|
||||||
|
return leftHeight + 1
|
||||||
|
}
|
||||||
|
return rightHeight + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Delete(targetName string) bool {
|
||||||
|
if bst.root == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_, found := bst.Search(targetName)
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
bst.root = bst.root.delete(targetName)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *BSTree) delete(targetName string) *BSTree {
|
||||||
|
if root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetName < root.data.Name {
|
||||||
|
root.left = root.left.delete(targetName)
|
||||||
|
} else if targetName > root.data.Name {
|
||||||
|
root.right = root.right.delete(targetName)
|
||||||
|
} else {
|
||||||
|
// Нашли узел для удаления
|
||||||
|
|
||||||
|
// Случай 1: нет левого потомка
|
||||||
|
if root.left == nil {
|
||||||
|
return root.right
|
||||||
|
}
|
||||||
|
|
||||||
|
// Случай 2: нет правого потомка
|
||||||
|
if root.right == nil {
|
||||||
|
return root.left
|
||||||
|
}
|
||||||
|
|
||||||
|
// Случай 3: оба потомка есть
|
||||||
|
successor := root.right.Minimum()
|
||||||
|
root.data = successor.data // Копируем все данные сразу
|
||||||
|
root.right = root.right.delete(successor.data.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) PrintAll() {
|
||||||
|
bst.root.printAll(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BSTree) printAll(depth int) {
|
||||||
|
if bst == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bst.right.printAll(depth + 1)
|
||||||
|
|
||||||
|
for i := 0; i < depth; i++ {
|
||||||
|
fmt.Printf("\t")
|
||||||
|
}
|
||||||
|
bst.PrintNode()
|
||||||
|
bst.left.printAll(depth + 1)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package hash_table
|
||||||
|
|
||||||
|
func GetHashString(str string) int {
|
||||||
|
hash := 0
|
||||||
|
|
||||||
|
for _, ch := range str {
|
||||||
|
hash = (hash << 5) - hash + int(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hash < 0 {
|
||||||
|
hash = -hash
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
package hash_table
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashTable - хеш-таблица с цепочками
|
||||||
|
type HashTable struct {
|
||||||
|
buckets []*bucket
|
||||||
|
size int
|
||||||
|
capacity int
|
||||||
|
loadFactor float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type bucket struct {
|
||||||
|
head *elementHT
|
||||||
|
}
|
||||||
|
|
||||||
|
type elementHT struct {
|
||||||
|
data ds.MyData
|
||||||
|
next *elementHT
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHashTable - создает новую хеш-таблицу
|
||||||
|
func NewHashTable(capacity int, loadFactor float64) *HashTable {
|
||||||
|
|
||||||
|
buckets := make([]*bucket, capacity)
|
||||||
|
|
||||||
|
for i := 0; i < capacity; i++ {
|
||||||
|
buckets[i] = &bucket{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &HashTable{
|
||||||
|
buckets: buckets,
|
||||||
|
size: 0,
|
||||||
|
capacity: capacity,
|
||||||
|
loadFactor: loadFactor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (h HashTable) getIndex(name string) int {
|
||||||
|
// return GetHashString(name) % h.size
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (h HashTable) Add(name string) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (ht *HashTable) GetIndex(name string) int {
|
||||||
|
hash := GetHashString(name)
|
||||||
|
return hash % ht.capacity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Len() int {
|
||||||
|
return ht.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (ht *HashTable) getIndex(hash int) int {
|
||||||
|
// return hash % ht.capacity
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (h *HashTable) Insert(new ds.MyData) {
|
||||||
|
|
||||||
|
if h.size >= int(float64(h.capacity)*h.loadFactor) {
|
||||||
|
h.resize()
|
||||||
|
}
|
||||||
|
|
||||||
|
ind := h.GetIndex(new.Name)
|
||||||
|
|
||||||
|
buck := h.buckets[ind]
|
||||||
|
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == new.Name {
|
||||||
|
current.data.Phone = new.Phone
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
newHead := &elementHT{
|
||||||
|
data: new,
|
||||||
|
next: buck.head,
|
||||||
|
}
|
||||||
|
|
||||||
|
buck.head = newHead
|
||||||
|
h.size++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) InsertAll(data []ds.MyData) {
|
||||||
|
for _, el := range data {
|
||||||
|
ht.Insert(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HashTable) Search(name string) (phone string, status bool) {
|
||||||
|
ind := h.GetIndex(name)
|
||||||
|
|
||||||
|
buck := h.buckets[ind]
|
||||||
|
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == name {
|
||||||
|
return current.data.Phone, true
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// func pressEnterToContinue() {
|
||||||
|
// fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
// bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
// }
|
||||||
|
|
||||||
|
// resize - увеличивает размер таблицы
|
||||||
|
func (ht *HashTable) resize() {
|
||||||
|
|
||||||
|
// fmt.Printf("Resize table!\n elements: %d(%.3f%%)\n old capacity: %d\n new capacity: %d\n", ht.size, float64(ht.size)/float64(ht.capacity), ht.capacity, 2*ht.capacity)
|
||||||
|
|
||||||
|
// ht.Print()
|
||||||
|
|
||||||
|
// pressEnterToContinue()
|
||||||
|
|
||||||
|
newCapacity := ht.capacity * 2
|
||||||
|
newHT := NewHashTable(newCapacity, ht.loadFactor)
|
||||||
|
|
||||||
|
for _, b := range ht.buckets {
|
||||||
|
current := b.head
|
||||||
|
for current != nil {
|
||||||
|
newHT.Insert(current.data)
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ht.buckets = newHT.buckets
|
||||||
|
ht.capacity = newCapacity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Delete(name string) bool {
|
||||||
|
ind := ht.GetIndex(name)
|
||||||
|
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
|
||||||
|
if buck.head == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if buck.head.data.Name == name {
|
||||||
|
buck.head = buck.head.next
|
||||||
|
ht.size--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
prev := buck.head
|
||||||
|
current := buck.head.next
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == name {
|
||||||
|
prev.next = current.next
|
||||||
|
ht.size--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
prev = current
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Contains(name string) bool {
|
||||||
|
_, ok := ht.Search(name)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (elem *elementHT) ToString() string {
|
||||||
|
if elem == nil {
|
||||||
|
return "nil"
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem.data.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Print() {
|
||||||
|
for ind := 0; ind < ht.capacity; ind++ {
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
bucketsStr := ""
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
bucketsStr += " --> " + current.ToString()
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
fmt.Printf("[%d]: %s\n", ind, bucketsStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) listAll() []ds.MyData {
|
||||||
|
data := make([]ds.MyData, ht.size)
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
|
||||||
|
for ind := 0; ind < ht.capacity; ind++ {
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
data[index] = current.data
|
||||||
|
index++
|
||||||
|
// fmt.Println(current.name, current.phone)
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) ListAll() []ds.MyData {
|
||||||
|
// fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
|
||||||
|
data := ht.listAll()
|
||||||
|
|
||||||
|
data = ds.QSort(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
// for i, el := range data {
|
||||||
|
// fmt.Printf("[%d]: \"%s\", %d\n", i, el.name, el.phone)
|
||||||
|
// }
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (ht *HashTable) PrintMostPopularnames(phone int) {
|
||||||
|
// // fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
|
||||||
|
// data := ht.listAll()
|
||||||
|
|
||||||
|
// data = QSortElementsHT(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
// for i := 0; i < phone; i++ {
|
||||||
|
// fmt.Printf("[%d]: %3d : %s\n", i, ht.GetIndex(data[len(data)-i-1].name), data[len(data)-i-1].ToString())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
package linked_list
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Связный список (LinkedListPhoneBook)
|
||||||
|
|
||||||
|
Узел представляется словарём: `{'name': 'Имя', 'phone': '123', 'next': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def ll_insert(head, name, phone) — проходит до конца (или сразу добавляет в конец) и возвращает новую голову (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||||
|
|
||||||
|
def ll_find(head, name) — ищет узел, возвращает телефон или None.
|
||||||
|
|
||||||
|
def ll_delete(head, name) — удаляет узел, возвращает новую голову.
|
||||||
|
|
||||||
|
def ll_list_all(head) — собирает все записи в список и сортирует (сортировка вынесена отдельно).
|
||||||
|
*/
|
||||||
|
|
||||||
|
type LinkedList struct {
|
||||||
|
head *LList
|
||||||
|
}
|
||||||
|
|
||||||
|
type LList struct {
|
||||||
|
data ds.MyData
|
||||||
|
|
||||||
|
next *LList
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinkedList() *LinkedList {
|
||||||
|
return &LinkedList{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLinkedList(data ds.MyData) *LList {
|
||||||
|
return &LList{
|
||||||
|
data: data,
|
||||||
|
next: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LList) ToString() string {
|
||||||
|
if ll == nil {
|
||||||
|
return "nil"
|
||||||
|
}
|
||||||
|
return ll.data.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Len() int {
|
||||||
|
|
||||||
|
if ll == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
len := 0
|
||||||
|
|
||||||
|
current := ll.head
|
||||||
|
for current != nil {
|
||||||
|
len++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Insert(data ds.MyData) {
|
||||||
|
newNode := newLinkedList(data)
|
||||||
|
|
||||||
|
if ll.head == nil {
|
||||||
|
ll.head = newNode
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
current := ll.head
|
||||||
|
for current.next != nil {
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
current.next = newNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) InsertAll(data []ds.MyData) {
|
||||||
|
for _, el := range data {
|
||||||
|
ll.Insert(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Search(targetName string) (string, bool) {
|
||||||
|
current := ll.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == targetName {
|
||||||
|
return current.data.Phone, true
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) PrintAll() {
|
||||||
|
current := ll.head
|
||||||
|
index := 0
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
fmt.Printf("[%d] %s\n", index, current.ToString())
|
||||||
|
index++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Delete(targetName string) bool {
|
||||||
|
if ll.head == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Особый случай: удаление головы списка
|
||||||
|
if ll.head.data.Name == targetName {
|
||||||
|
// Сдвигаем данные и указатель
|
||||||
|
*ll.head = *ll.head.next
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Стандартное удаление из середины/конца
|
||||||
|
current := ll.head
|
||||||
|
for current.next != nil {
|
||||||
|
if current.next.data.Name == targetName {
|
||||||
|
current.next = current.next.next
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) listAll() []ds.MyData {
|
||||||
|
current := ll.head
|
||||||
|
|
||||||
|
listLL := make([]ds.MyData, ll.Len())
|
||||||
|
ind := 0
|
||||||
|
for current != nil {
|
||||||
|
listLL[ind] = current.data
|
||||||
|
ind++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
listLL = ds.QSort(listLL, 0, len(listLL)-1)
|
||||||
|
return listLL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) GetByInd(ind int) (ds.MyData, bool) {
|
||||||
|
if ind >= ll.Len() {
|
||||||
|
return ds.MyData{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
current := ll.head
|
||||||
|
for current != nil {
|
||||||
|
if index == ind {
|
||||||
|
return current.data, true
|
||||||
|
}
|
||||||
|
current = current.next
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
|
return ds.MyData{}, false
|
||||||
|
}
|
||||||
379
stepushovgs/data-structures/source/results/benchmarks.csv
Normal file
379
stepushovgs/data-structures/source/results/benchmarks.csv
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
Structure,Mode,Operation,Time
|
||||||
|
Связный список,Случайный,Вставка,0.199516
|
||||||
|
Связный список,Случайный,Поиск,0.024629
|
||||||
|
Связный список,Случайный,Удаление,0.014065
|
||||||
|
Связный список,Случайный,Вставка,0.196946
|
||||||
|
Связный список,Случайный,Поиск,0.023807
|
||||||
|
Связный список,Случайный,Удаление,0.013115
|
||||||
|
Связный список,Случайный,Вставка,0.191475
|
||||||
|
Связный список,Случайный,Поиск,0.023083
|
||||||
|
Связный список,Случайный,Удаление,0.014584
|
||||||
|
Связный список,Случайный,Вставка,0.189964
|
||||||
|
Связный список,Случайный,Поиск,0.024014
|
||||||
|
Связный список,Случайный,Удаление,0.014049
|
||||||
|
Связный список,Случайный,Вставка,0.192273
|
||||||
|
Связный список,Случайный,Поиск,0.023643
|
||||||
|
Связный список,Случайный,Удаление,0.013426
|
||||||
|
Связный список,Случайный,Вставка,0.191623
|
||||||
|
Связный список,Случайный,Поиск,0.022900
|
||||||
|
Связный список,Случайный,Удаление,0.014242
|
||||||
|
Связный список,Случайный,Вставка,0.192131
|
||||||
|
Связный список,Случайный,Поиск,0.024910
|
||||||
|
Связный список,Случайный,Удаление,0.013999
|
||||||
|
Связный список,Случайный,Вставка,0.190054
|
||||||
|
Связный список,Случайный,Поиск,0.023244
|
||||||
|
Связный список,Случайный,Удаление,0.014556
|
||||||
|
Связный список,Случайный,Вставка,0.199543
|
||||||
|
Связный список,Случайный,Поиск,0.023660
|
||||||
|
Связный список,Случайный,Удаление,0.015066
|
||||||
|
Связный список,Случайный,Вставка,0.193103
|
||||||
|
Связный список,Случайный,Поиск,0.023620
|
||||||
|
Связный список,Случайный,Удаление,0.014555
|
||||||
|
Связный список,Случайный,Вставка,0.191255
|
||||||
|
Связный список,Случайный,Поиск,0.023310
|
||||||
|
Связный список,Случайный,Удаление,0.014155
|
||||||
|
Связный список,Случайный,Вставка,0.190051
|
||||||
|
Связный список,Случайный,Поиск,0.023622
|
||||||
|
Связный список,Случайный,Удаление,0.014049
|
||||||
|
Связный список,Случайный,Вставка,0.194320
|
||||||
|
Связный список,Случайный,Поиск,0.024634
|
||||||
|
Связный список,Случайный,Удаление,0.014369
|
||||||
|
Связный список,Случайный,Вставка,0.191525
|
||||||
|
Связный список,Случайный,Поиск,0.023547
|
||||||
|
Связный список,Случайный,Удаление,0.014032
|
||||||
|
Связный список,Случайный,Вставка,0.189879
|
||||||
|
Связный список,Случайный,Поиск,0.022658
|
||||||
|
Связный список,Случайный,Удаление,0.014757
|
||||||
|
Связный список,Случайный,Вставка,0.193771
|
||||||
|
Связный список,Случайный,Поиск,0.023675
|
||||||
|
Связный список,Случайный,Удаление,0.014797
|
||||||
|
Связный список,Случайный,Вставка,0.203894
|
||||||
|
Связный список,Случайный,Поиск,0.025087
|
||||||
|
Связный список,Случайный,Удаление,0.014177
|
||||||
|
Связный список,Случайный,Вставка,0.192419
|
||||||
|
Связный список,Случайный,Поиск,0.023327
|
||||||
|
Связный список,Случайный,Удаление,0.014068
|
||||||
|
Связный список,Случайный,Вставка,0.191059
|
||||||
|
Связный список,Случайный,Поиск,0.023409
|
||||||
|
Связный список,Случайный,Удаление,0.013834
|
||||||
|
Связный список,Случайный,Вставка,0.192096
|
||||||
|
Связный список,Случайный,Поиск,0.023889
|
||||||
|
Связный список,Случайный,Удаление,0.015085
|
||||||
|
Связный список,Случайный,Вставка (среднее),0.193345
|
||||||
|
Связный список,Случайный,Поиск (среднее),0.023733
|
||||||
|
Связный список,Случайный,Удаление (среднее),0.014249
|
||||||
|
Связный список,Отсортированный,Вставка,0.193317
|
||||||
|
Связный список,Отсортированный,Поиск,0.033389
|
||||||
|
Связный список,Отсортированный,Удаление,0.023146
|
||||||
|
Связный список,Отсортированный,Вставка,0.190249
|
||||||
|
Связный список,Отсортированный,Поиск,0.032418
|
||||||
|
Связный список,Отсортированный,Удаление,0.023950
|
||||||
|
Связный список,Отсортированный,Вставка,0.193341
|
||||||
|
Связный список,Отсортированный,Поиск,0.033679
|
||||||
|
Связный список,Отсортированный,Удаление,0.024198
|
||||||
|
Связный список,Отсортированный,Вставка,0.192107
|
||||||
|
Связный список,Отсортированный,Поиск,0.035083
|
||||||
|
Связный список,Отсортированный,Удаление,0.031384
|
||||||
|
Связный список,Отсортированный,Вставка,0.196266
|
||||||
|
Связный список,Отсортированный,Поиск,0.033967
|
||||||
|
Связный список,Отсортированный,Удаление,0.023633
|
||||||
|
Связный список,Отсортированный,Вставка,0.193438
|
||||||
|
Связный список,Отсортированный,Поиск,0.033898
|
||||||
|
Связный список,Отсортированный,Удаление,0.022652
|
||||||
|
Связный список,Отсортированный,Вставка,0.192293
|
||||||
|
Связный список,Отсортированный,Поиск,0.033186
|
||||||
|
Связный список,Отсортированный,Удаление,0.024209
|
||||||
|
Связный список,Отсортированный,Вставка,0.193963
|
||||||
|
Связный список,Отсортированный,Поиск,0.041383
|
||||||
|
Связный список,Отсортированный,Удаление,0.027010
|
||||||
|
Связный список,Отсортированный,Вставка,0.191974
|
||||||
|
Связный список,Отсортированный,Поиск,0.033188
|
||||||
|
Связный список,Отсортированный,Удаление,0.024141
|
||||||
|
Связный список,Отсортированный,Вставка,0.193575
|
||||||
|
Связный список,Отсортированный,Поиск,0.034097
|
||||||
|
Связный список,Отсортированный,Удаление,0.023053
|
||||||
|
Связный список,Отсортированный,Вставка,0.195551
|
||||||
|
Связный список,Отсортированный,Поиск,0.033767
|
||||||
|
Связный список,Отсортированный,Удаление,0.023550
|
||||||
|
Связный список,Отсортированный,Вставка,0.193096
|
||||||
|
Связный список,Отсортированный,Поиск,0.034052
|
||||||
|
Связный список,Отсортированный,Удаление,0.023542
|
||||||
|
Связный список,Отсортированный,Вставка,0.192483
|
||||||
|
Связный список,Отсортированный,Поиск,0.033566
|
||||||
|
Связный список,Отсортированный,Удаление,0.023538
|
||||||
|
Связный список,Отсортированный,Вставка,0.191346
|
||||||
|
Связный список,Отсортированный,Поиск,0.033764
|
||||||
|
Связный список,Отсортированный,Удаление,0.023127
|
||||||
|
Связный список,Отсортированный,Вставка,0.191555
|
||||||
|
Связный список,Отсортированный,Поиск,0.033191
|
||||||
|
Связный список,Отсортированный,Удаление,0.024127
|
||||||
|
Связный список,Отсортированный,Вставка,0.190323
|
||||||
|
Связный список,Отсортированный,Поиск,0.033676
|
||||||
|
Связный список,Отсортированный,Удаление,0.023664
|
||||||
|
Связный список,Отсортированный,Вставка,0.192296
|
||||||
|
Связный список,Отсортированный,Поиск,0.032708
|
||||||
|
Связный список,Отсортированный,Удаление,0.024118
|
||||||
|
Связный список,Отсортированный,Вставка,0.204537
|
||||||
|
Связный список,Отсортированный,Поиск,0.041774
|
||||||
|
Связный список,Отсортированный,Удаление,0.026976
|
||||||
|
Связный список,Отсортированный,Вставка,0.193468
|
||||||
|
Связный список,Отсортированный,Поиск,0.033044
|
||||||
|
Связный список,Отсортированный,Удаление,0.023545
|
||||||
|
Связный список,Отсортированный,Вставка,0.204401
|
||||||
|
Связный список,Отсортированный,Поиск,0.035750
|
||||||
|
Связный список,Отсортированный,Удаление,0.026609
|
||||||
|
Связный список,Отсортированный,Вставка (среднее),0.193979
|
||||||
|
Связный список,Отсортированный,Поиск (среднее),0.034479
|
||||||
|
Связный список,Отсортированный,Удаление (среднее),0.024509
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003026
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003299
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003808
|
||||||
|
Хеш таблица,Случайный,Поиск,0.001001
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003292
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004268
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003100
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004619
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004010
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.002825
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004394
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003335
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004183
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.002352
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.004124
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003422
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.002977
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.005030
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003815
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003015
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка,0.003805
|
||||||
|
Хеш таблица,Случайный,Поиск,0.000000
|
||||||
|
Хеш таблица,Случайный,Удаление,0.000000
|
||||||
|
Хеш таблица,Случайный,Вставка (среднее),0.003635
|
||||||
|
Хеш таблица,Случайный,Поиск (среднее),0.000050
|
||||||
|
Хеш таблица,Случайный,Удаление (среднее),0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.002509
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003017
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003126
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.001002
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.002257
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003013
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.001668
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.002519
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003346
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.004243
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.001588
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.001585
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003053
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003009
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003074
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.001185
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003145
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.004152
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.004280
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003098
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.004386
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003416
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.002529
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка,0.003863
|
||||||
|
Хеш таблица,Отсортированный,Поиск,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Удаление,0.000000
|
||||||
|
Хеш таблица,Отсортированный,Вставка (среднее),0.003181
|
||||||
|
Хеш таблица,Отсортированный,Поиск (среднее),0.000109
|
||||||
|
Хеш таблица,Отсортированный,Удаление (среднее),0.000163
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.004532
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001019
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005690
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001004
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005536
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.001001
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.008002
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.007454
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.001012
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.006524
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.004504
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.007206
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.006102
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.007414
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001003
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005723
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001503
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005705
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.001007
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.006501
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001005
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005375
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.001000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.004520
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.001006
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005931
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.001034
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.007446
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000634
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000521
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005628
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000513
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000510
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.005162
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000511
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000512
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка,0.006672
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск,0.000000
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление,0.000549
|
||||||
|
Бинарное дерево поиска,Случайный,Вставка (среднее),0.006081
|
||||||
|
Бинарное дерево поиска,Случайный,Поиск (среднее),0.000336
|
||||||
|
Бинарное дерево поиска,Случайный,Удаление (среднее),0.000481
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.993672
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060430
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.065743
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.984657
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060576
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.067630
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,1.077915
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.064100
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.066554
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.986610
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060386
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.065383
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.976014
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060724
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.066072
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.954288
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.062234
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.067913
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.948662
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.061164
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064309
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.940560
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.058861
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.065901
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.944873
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060448
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.065882
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.928810
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.061107
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064740
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.925909
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060174
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064934
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.926721
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.062980
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.062940
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.932508
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.059849
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064563
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.941225
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.058925
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.062112
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.935714
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.059868
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064928
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.925400
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.060723
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.063271
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.935481
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.059515
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.063816
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.930136
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.057873
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.063642
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.931535
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.059197
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.064474
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка,0.933106
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск,0.062731
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление,0.062908
|
||||||
|
Бинарное дерево поиска,Отсортированный,Вставка (среднее),0.952690
|
||||||
|
Бинарное дерево поиска,Отсортированный,Поиск (среднее),0.060593
|
||||||
|
Бинарное дерево поиска,Отсортированный,Удаление (среднее),0.064886
|
||||||
|
288
stepushovgs/data-structures/source/tests/benchmark/main.go
Normal file
288
stepushovgs/data-structures/source/tests/benchmark/main.go
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
csvwriter "source/pkg/csv_writer"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
dg "source/pkg/gen_data"
|
||||||
|
bst "source/pkg/structures/bin_search_tree"
|
||||||
|
ht "source/pkg/structures/hash_table"
|
||||||
|
ll "source/pkg/structures/linked_list"
|
||||||
|
|
||||||
|
// csv "source/pkg/csv_ri"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
countUsers = 20_000
|
||||||
|
countRepeat = 20
|
||||||
|
countRandomSearch = 1000
|
||||||
|
countNotExitstSearch = 500
|
||||||
|
countDeletes = 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestData struct {
|
||||||
|
Items []ds.MyData // все записи
|
||||||
|
ItemsSorted []ds.MyData // все записи отсортированные
|
||||||
|
Search []ds.MyData // для поиска (существующие и несуществующие)
|
||||||
|
ToDelete []ds.MyData // для удаления
|
||||||
|
UniqueItems []ds.MyData // Уникальные элементы для тестов
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataStructure interface {
|
||||||
|
Insert(data ds.MyData)
|
||||||
|
InsertAll(data []ds.MyData)
|
||||||
|
Search(name string) (string, bool)
|
||||||
|
Delete(name string) bool
|
||||||
|
Len() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создатели структур
|
||||||
|
type StructureFactory func() DataStructure
|
||||||
|
|
||||||
|
func NewLinkedList() DataStructure {
|
||||||
|
return ll.NewLinkedList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHashTable() DataStructure {
|
||||||
|
return ht.NewHashTable(256, 0.75)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBinSearchTree() DataStructure {
|
||||||
|
return bst.NewBinSearchTree()
|
||||||
|
}
|
||||||
|
|
||||||
|
func uniqueElements(data []ds.MyData) []ds.MyData {
|
||||||
|
res := make([]ds.MyData, 0, len(data))
|
||||||
|
|
||||||
|
for _, el := range data {
|
||||||
|
isUnique := true
|
||||||
|
for _, resEl := range res {
|
||||||
|
if el == resEl {
|
||||||
|
isUnique = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isUnique {
|
||||||
|
res = append(res, el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateTestData() TestData {
|
||||||
|
items := dg.RecordsShuffled(countUsers)
|
||||||
|
// fmt.Println("isSorted:", isSorted(items))
|
||||||
|
itemsSort := ds.QSort(items, 0, len(items)-1)
|
||||||
|
|
||||||
|
uniqueItems := uniqueElements(items)
|
||||||
|
existing := make([]ds.MyData, countRandomSearch)
|
||||||
|
// notExisting := [countNotExitstSearch]ds.MyData{}
|
||||||
|
notExisting := make([]ds.MyData, countNotExitstSearch)
|
||||||
|
toDelete := make([]ds.MyData, countDeletes)
|
||||||
|
|
||||||
|
countUniq := len(uniqueItems)
|
||||||
|
for i := 0; i < countRandomSearch; i++ {
|
||||||
|
// randInd := rand.Intn(countUsers)
|
||||||
|
randInd := rand.Intn(countUniq)
|
||||||
|
existing[i] = uniqueItems[randInd]
|
||||||
|
// fmt.Println(randInd)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < countNotExitstSearch; i++ {
|
||||||
|
// randInd := rand.Intn(countUsers)
|
||||||
|
randInd := rand.Intn(10)
|
||||||
|
name := fmt.Sprintf("User_%d", randInd)
|
||||||
|
notExisting[i] = *ds.NewData(name, "")
|
||||||
|
// fmt.Println(randInd)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, el := range notExisting {
|
||||||
|
existing = append(existing, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
// toDelete = make([]ds.MyData, countDeletes)
|
||||||
|
usedIndices := make(map[int]bool)
|
||||||
|
for i := 0; i < countDeletes; i++ {
|
||||||
|
var randInd int
|
||||||
|
for {
|
||||||
|
randInd = rand.Intn(countUniq)
|
||||||
|
if !usedIndices[randInd] {
|
||||||
|
usedIndices[randInd] = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toDelete[i] = uniqueItems[randInd]
|
||||||
|
}
|
||||||
|
|
||||||
|
return TestData{
|
||||||
|
Items: items,
|
||||||
|
ItemsSorted: itemsSort,
|
||||||
|
Search: existing,
|
||||||
|
ToDelete: toDelete,
|
||||||
|
UniqueItems: uniqueItems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Тест вставки массива данных (один раз)
|
||||||
|
func testOnesInsert(structure DataStructure, data []ds.MyData) float64 {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for _, item := range data {
|
||||||
|
structure.Insert(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Since(start).Seconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Тест поиска массива данных (один раз)
|
||||||
|
func testOnesSearch(structure DataStructure, data []ds.MyData) float64 {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
// flag := true
|
||||||
|
|
||||||
|
for _, item := range data {
|
||||||
|
structure.Search(item.Name)
|
||||||
|
// p, ok := structure.Search(item.Name)
|
||||||
|
|
||||||
|
// if flag {
|
||||||
|
// flag = ((p == item.Phone) == ok)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt.Println(flag)
|
||||||
|
|
||||||
|
return time.Since(start).Seconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Тест удаления массива данных (один раз)
|
||||||
|
func testOnesDelete(structure DataStructure, data []ds.MyData) float64 {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for _, item := range data {
|
||||||
|
structure.Delete(item.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Since(start).Seconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testForData(nameStruct, mode string, factory StructureFactory, data_insert, data_search, data_delete []ds.MyData) {
|
||||||
|
BenchRes := make([]csvwriter.BenchmarkResult, 0, countRepeat*3+3) // Массив строк отчёта
|
||||||
|
|
||||||
|
averageTimeInsert := 0.
|
||||||
|
averageTimeSearch := 0.
|
||||||
|
averageTimeDelete := 0.
|
||||||
|
|
||||||
|
for iteration := 0; iteration < countRepeat; iteration++ {
|
||||||
|
|
||||||
|
structure := factory()
|
||||||
|
|
||||||
|
insertTime := testOnesInsert(structure, data_insert)
|
||||||
|
averageTimeInsert += insertTime
|
||||||
|
|
||||||
|
// Отладочная информация для бинарного дерева (проверка на вырождение)
|
||||||
|
if bst, ok := structure.(*bst.BinSearchTree); ok {
|
||||||
|
fmt.Printf(
|
||||||
|
"Высота дерева: %d, элементов: %d\n",
|
||||||
|
bst.Height(), bst.Len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Вставка",
|
||||||
|
Time: insertTime,
|
||||||
|
})
|
||||||
|
|
||||||
|
searchTime := testOnesSearch(structure, data_search)
|
||||||
|
averageTimeSearch += searchTime
|
||||||
|
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Поиск",
|
||||||
|
Time: searchTime,
|
||||||
|
})
|
||||||
|
|
||||||
|
deleteTime := testOnesDelete(structure, data_delete)
|
||||||
|
averageTimeDelete += deleteTime
|
||||||
|
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Удаление",
|
||||||
|
Time: deleteTime,
|
||||||
|
})
|
||||||
|
fmt.Printf("%s | Вставка | %s | Время: %f\n", nameStruct, mode, insertTime)
|
||||||
|
fmt.Printf("%s | Поиск | %s | Время: %f\n", nameStruct, mode, searchTime)
|
||||||
|
fmt.Printf("%s | Удаление | %s | Время: %.9f\n", nameStruct, mode, deleteTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
averageTimeInsert /= countRepeat
|
||||||
|
averageTimeSearch /= countRepeat
|
||||||
|
averageTimeDelete /= countRepeat
|
||||||
|
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Вставка (среднее)",
|
||||||
|
Time: averageTimeInsert,
|
||||||
|
})
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Поиск (среднее)",
|
||||||
|
Time: averageTimeSearch,
|
||||||
|
})
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Удаление (среднее)",
|
||||||
|
Time: averageTimeDelete,
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("%s | Вставка | %s | Время (среднее): %f\n", nameStruct, mode, averageTimeInsert)
|
||||||
|
fmt.Printf("%s | Поиск | %s | Время (среднее): %f\n", nameStruct, mode, averageTimeSearch)
|
||||||
|
fmt.Printf("%s | Удаление | %s | Время (среднее): %f\n", nameStruct, mode, averageTimeDelete)
|
||||||
|
|
||||||
|
csvwriter.AppendRaw(BenchRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSorted(data []ds.MyData) bool {
|
||||||
|
for i := 0; i < len(data)-1; i++ {
|
||||||
|
if data[i].Name > data[i+1].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(nameStruct string, factory StructureFactory) {
|
||||||
|
data := GenerateTestData()
|
||||||
|
|
||||||
|
// fmt.Println("items", isSorted(data.Items))
|
||||||
|
// fmt.Println("items sort", isSorted(data.ItemsSorted))
|
||||||
|
|
||||||
|
testForData(nameStruct, "Случайный", factory, data.Items, data.Search, data.ToDelete)
|
||||||
|
|
||||||
|
testForData(nameStruct, "Отсортированный", factory, data.ItemsSorted, data.Search, data.ToDelete)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
csvwriter.CreateEmptyCSV("results", "benchmarks.csv")
|
||||||
|
|
||||||
|
fmt.Println("============= Начало тестов =============")
|
||||||
|
|
||||||
|
Test("Связный список", NewLinkedList)
|
||||||
|
Test("Хеш таблица", NewHashTable)
|
||||||
|
Test("Бинарное дерево поиска", NewBinSearchTree)
|
||||||
|
|
||||||
|
// fmt.Println("User_0001" < "User_00100")
|
||||||
|
// fmt.Println(isSorted(dg.RecordsShuffled(10000)))
|
||||||
|
}
|
||||||
50
stepushovgs/data-structures/source/tests/test_bst/main.go
Normal file
50
stepushovgs/data-structures/source/tests/test_bst/main.go
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
bst "source/pkg/structures/bin_search_tree"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
countNumbers = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
func pressEnterToContinue() {
|
||||||
|
fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// isInArr проверяет, содержится ли target в срезе arr[:len]
|
||||||
|
func isInArr(arr []int, length int, target int) bool {
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
if arr[i] == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world!")
|
||||||
|
|
||||||
|
head := bst.NewBinSearchTree()
|
||||||
|
|
||||||
|
for i := 1; i <= 20; i++ {
|
||||||
|
name := fmt.Sprintf("User_%02d", i)
|
||||||
|
phone := fmt.Sprintf("Phone_%02d", i)
|
||||||
|
head.Insert(*ds.NewData(name, phone))
|
||||||
|
}
|
||||||
|
|
||||||
|
head.BstInorderTraversal()
|
||||||
|
|
||||||
|
head.Delete("User_05")
|
||||||
|
fmt.Println("Удаляем User_05")
|
||||||
|
|
||||||
|
head.BstInorderTraversal()
|
||||||
|
|
||||||
|
fmt.Println(head.Search("User_07"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
csvwriter "source/pkg/csv_writer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Простой способ
|
||||||
|
results := []csvwriter.BenchmarkResult{
|
||||||
|
{Structure: "HashTable", Mode: "Chaining", Operation: "Insert", Time: 0.001234},
|
||||||
|
{Structure: "LinkedList", Mode: "Singly", Operation: "Search", Time: 0.005678},
|
||||||
|
{Structure: "BSTree", Mode: "Recursive", Operation: "Delete", Time: 0.003456},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := csvwriter.AppendRaw(results); err != nil {
|
||||||
|
fmt.Printf("Ошибка: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
90
stepushovgs/data-structures/source/tests/test_ht/main.go
Normal file
90
stepushovgs/data-structures/source/tests/test_ht/main.go
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
// hash_table "hash-table-task/hash-table"
|
||||||
|
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
ht "source/pkg/structures/hash_table"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
1. Сконструировать и реализовать свою хеш таблицу
|
||||||
|
|
||||||
|
- изначальный размер 8, коэф-т загрузки 0.75
|
||||||
|
|
||||||
|
- Преобразование подаваемого данного в индекс с помощью хеш функции(в ручну) пример: полиномиальный хеш
|
||||||
|
|
||||||
|
- Коллизии обрабатываются методом цепочек, каждая корзина таблицы - список в котором хранятся пары значений key-value
|
||||||
|
|
||||||
|
- При превышении коэф-та загрузки происходит перехеширование таблицы, размер увеличивается вдвое, все пары заново вставляются в таблицу.
|
||||||
|
|
||||||
|
2. Читаем текстовый файл, разбивает на слова, приводим к нижнему регистру, подсчитываем повторения каждого слова: key - слово, value - кол-во повторений
|
||||||
|
|
||||||
|
- На вывод 10 самых встречающихся слов, для каждого слова выводим: ind(hash), key, value
|
||||||
|
- Текст - первая глава, первые три стиха Евгений Онегин
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world")
|
||||||
|
head := ht.NewHashTable(8, 0.75)
|
||||||
|
|
||||||
|
for i := 1; i <= 40; i++ {
|
||||||
|
name := fmt.Sprintf("User_%02d", i)
|
||||||
|
phone := fmt.Sprintf("Phone_%02d", i)
|
||||||
|
head.Insert(*ds.NewData(name, phone))
|
||||||
|
}
|
||||||
|
|
||||||
|
head.Print()
|
||||||
|
|
||||||
|
head.Delete("User_05")
|
||||||
|
fmt.Println("Удаляем User_05")
|
||||||
|
|
||||||
|
head.Print()
|
||||||
|
|
||||||
|
fmt.Println(head.Search("User_07"))
|
||||||
|
|
||||||
|
// Чтение всего файла
|
||||||
|
|
||||||
|
// const filePath = "../data/onegin.txt"
|
||||||
|
// // const filePath = "../data/onegin_full.txt"
|
||||||
|
|
||||||
|
// data, err := os.ReadFile(filePath)
|
||||||
|
// text := string(data)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println("Ошибка чтения файла:", err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// fmt.Println(text)
|
||||||
|
|
||||||
|
// text = strings.ToLower(text)
|
||||||
|
|
||||||
|
// // Разбиение на слова (разделители: пробелы и переводы строк)
|
||||||
|
// re := regexp.MustCompile(`[\p{L}\p{N}-]+`)
|
||||||
|
// words := re.FindAllString(text, -1)
|
||||||
|
|
||||||
|
// fmt.Printf("Найдено слов: %d\n", len(words))
|
||||||
|
// for i, word := range words {
|
||||||
|
// fmt.Printf("Слово %d: %s\n", i+1, word)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// hashTable := ht.NewHashTable(8, 0.95)
|
||||||
|
|
||||||
|
// for i, word := range words {
|
||||||
|
// fmt.Printf("%d : %s\n", i, word)
|
||||||
|
// hashTable.Put(word, 1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Println("\nХеш таблица текста: ")
|
||||||
|
// hashTable.Print()
|
||||||
|
|
||||||
|
// // fmt.Println("Отсортированные ячейки таблицы: ")
|
||||||
|
// // hashTable.PrintSort()
|
||||||
|
|
||||||
|
// fmt.Println("\nСамые часто встречающиеся слова: ")
|
||||||
|
|
||||||
|
// // hashTable.PrintMostPopularWords(10)
|
||||||
|
}
|
||||||
52
stepushovgs/data-structures/source/tests/test_ll/main.go
Normal file
52
stepushovgs/data-structures/source/tests/test_ll/main.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
|
||||||
|
// rs "source/pkg/resulter"
|
||||||
|
ll "source/pkg/structures/linked_list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isInArr(arr []int, length int, target int) bool {
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
if arr[i] == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Razdelitel() {
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
fmt.Print("-")
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
func pressEnterToContinue() {
|
||||||
|
fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world!")
|
||||||
|
|
||||||
|
head := ll.NewLinkedList()
|
||||||
|
|
||||||
|
for i := 1; i <= 20; i++ {
|
||||||
|
name := fmt.Sprintf("User_%02d", i)
|
||||||
|
phone := fmt.Sprintf("Phone_%02d", i)
|
||||||
|
head.Insert(*ds.NewData(name, phone))
|
||||||
|
}
|
||||||
|
|
||||||
|
head.PrintAll()
|
||||||
|
|
||||||
|
head.Delete("User_05")
|
||||||
|
|
||||||
|
head.PrintAll()
|
||||||
|
|
||||||
|
fmt.Println(head.Search("User_07"))
|
||||||
|
}
|
||||||
11255
stepushovgs/labyrinth/benchmark.ipynb
Normal file
11255
stepushovgs/labyrinth/benchmark.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
221
stepushovgs/labyrinth/docs/data/csv/banchmark.csv
Normal file
221
stepushovgs/labyrinth/docs/data/csv/banchmark.csv
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
Лабиринт,Алгоритм,Время,Посещено клеток,Длина пути
|
||||||
|
maze10x10,BFS,0.0744000026315916,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0757000016164965,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0727000006008893,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0742999982321634,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0537000014446675,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0547000017832033,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0569000003451947,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0665000006847549,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0543999994988553,25.0,16.0
|
||||||
|
maze10x10,BFS,0.0548999996681232,25.0,16.0
|
||||||
|
maze10x10(среднее),BFS,0.063820000650594,25.0,16.0
|
||||||
|
maze50x50,BFS,1.4375999999174385,972.0,176.0
|
||||||
|
maze50x50,BFS,1.698000000033062,972.0,176.0
|
||||||
|
maze50x50,BFS,1.5351000001828652,972.0,176.0
|
||||||
|
maze50x50,BFS,1.5220999994198792,972.0,176.0
|
||||||
|
maze50x50,BFS,1.574800000526011,972.0,176.0
|
||||||
|
maze50x50,BFS,1.4951999983168207,972.0,176.0
|
||||||
|
maze50x50,BFS,1.511999998911051,972.0,176.0
|
||||||
|
maze50x50,BFS,1.5139999995881226,972.0,176.0
|
||||||
|
maze50x50,BFS,1.4908999983163085,972.0,176.0
|
||||||
|
maze50x50,BFS,1.487499997892883,972.0,176.0
|
||||||
|
maze50x50(среднее),BFS,1.526719999310444,972.0,176.0
|
||||||
|
maze100x100,BFS,3.02670000019134,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.52529999872786,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.663800001959317,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.517799999826821,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.506500001094537,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.690400000778027,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.396100000827573,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.629499999078689,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.8606999987678137,2345.0,197.0
|
||||||
|
maze100x100,BFS,3.4976999995706137,2345.0,197.0
|
||||||
|
maze100x100(среднее),BFS,3.531450000082259,2345.0,197.0
|
||||||
|
maze_empty,BFS,8.452400001260685,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.42489999922691,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.638600000267616,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.208700000977842,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.816000001388602,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.447899999737274,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.679799997480586,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.399000002100365,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.234299999458017,5328.0,158.0
|
||||||
|
maze_empty,BFS,8.313599999382859,5328.0,158.0
|
||||||
|
maze_empty(среднее),BFS,8.461520000128075,5328.0,158.0
|
||||||
|
maze_no_path,BFS,1.6376999992644414,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.7487000004621225,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.933600000484148,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.8192999996244907,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.8314999979338609,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.9929000009142328,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.7305000001215376,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.6904000003705733,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.6647000011289492,1245.0,0.0
|
||||||
|
maze_no_path,BFS,1.733000000967877,1245.0,0.0
|
||||||
|
maze_no_path(среднее),BFS,1.778230000127223,1245.0,0.0
|
||||||
|
maze10x10,DFS,0.0433999994129408,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0624999993306119,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0682999998389277,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0490999991598073,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0468999969598371,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0467999998363666,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0689000007696449,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0502000002597924,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0493999978061765,24.0,16.0
|
||||||
|
maze10x10,DFS,0.0475000015285331,24.0,16.0
|
||||||
|
maze10x10(среднее),DFS,0.0532999994902638,24.0,16.0
|
||||||
|
maze50x50,DFS,1.184500000817934,920.0,176.0
|
||||||
|
maze50x50,DFS,1.274300000659423,920.0,176.0
|
||||||
|
maze50x50,DFS,1.3567999994847924,920.0,176.0
|
||||||
|
maze50x50,DFS,1.27749999955995,920.0,176.0
|
||||||
|
maze50x50,DFS,1.4292000014393125,920.0,176.0
|
||||||
|
maze50x50,DFS,1.2790999971912242,920.0,176.0
|
||||||
|
maze50x50,DFS,1.329700000496814,920.0,176.0
|
||||||
|
maze50x50,DFS,1.257100000657374,920.0,176.0
|
||||||
|
maze50x50,DFS,1.4220000011846423,920.0,176.0
|
||||||
|
maze50x50,DFS,1.372599999740487,920.0,176.0
|
||||||
|
maze50x50(среднее),DFS,1.3182800001231954,920.0,176.0
|
||||||
|
maze100x100,DFS,3.26380000115023,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.768599999602884,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.677199998492142,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.6672999995062128,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.9711999997962266,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.7203000028966926,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.739499999937834,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.717999999935273,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.63140000263229,2609.0,197.0
|
||||||
|
maze100x100,DFS,3.789499998674728,2609.0,197.0
|
||||||
|
maze100x100(среднее),DFS,3.6946800002624514,2609.0,197.0
|
||||||
|
maze_empty,DFS,5.714499999157852,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.989400000544265,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.901900000026217,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.935400000453228,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.898100000194972,5328.0,2578.0
|
||||||
|
maze_empty,DFS,6.119699999544537,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.7996000032289885,5328.0,2578.0
|
||||||
|
maze_empty,DFS,6.074900000385242,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.99549999969895,5328.0,2578.0
|
||||||
|
maze_empty,DFS,5.661700000928249,5328.0,2578.0
|
||||||
|
maze_empty(среднее),DFS,5.90907000041625,5328.0,2578.0
|
||||||
|
maze_no_path,DFS,2.58909999683965,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.87980000191601,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.6818000003695488,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.8071000013151208,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.6453999996883797,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.7989999978453852,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.778600002580788,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.668100001552375,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.6705999987607356,1245.0,0.0
|
||||||
|
maze_no_path,DFS,1.7055999996955509,1245.0,0.0
|
||||||
|
maze_no_path(среднее),DFS,1.8225100000563543,1245.0,0.0
|
||||||
|
maze10x10,A*,0.0639999998384155,24.0,16.0
|
||||||
|
maze10x10,A*,0.0728000013623386,24.0,16.0
|
||||||
|
maze10x10,A*,0.0684000006003771,24.0,16.0
|
||||||
|
maze10x10,A*,0.0645000000076834,24.0,16.0
|
||||||
|
maze10x10,A*,0.0641000005998648,24.0,16.0
|
||||||
|
maze10x10,A*,0.0661000012769363,24.0,16.0
|
||||||
|
maze10x10,A*,0.0680000011925585,24.0,16.0
|
||||||
|
maze10x10,A*,0.0658999997540377,24.0,16.0
|
||||||
|
maze10x10,A*,0.0686999992467463,24.0,16.0
|
||||||
|
maze10x10,A*,0.0715000023774337,24.0,16.0
|
||||||
|
maze10x10(среднее),A*,0.0674000006256392,24.0,16.0
|
||||||
|
maze50x50,A*,1.6070000019681174,763.0,176.0
|
||||||
|
maze50x50,A*,1.840099997934885,763.0,176.0
|
||||||
|
maze50x50,A*,1.7380999997840263,763.0,176.0
|
||||||
|
maze50x50,A*,1.808999997592764,763.0,176.0
|
||||||
|
maze50x50,A*,1.6594000007899012,763.0,176.0
|
||||||
|
maze50x50,A*,1.821499998186482,763.0,176.0
|
||||||
|
maze50x50,A*,1.6746000001148786,763.0,176.0
|
||||||
|
maze50x50,A*,2.4415000007138588,763.0,176.0
|
||||||
|
maze50x50,A*,2.8442000002542045,763.0,176.0
|
||||||
|
maze50x50,A*,1.8294000001333188,763.0,176.0
|
||||||
|
maze50x50(среднее),A*,1.926479999747244,763.0,176.0
|
||||||
|
maze100x100,A*,2.5787000013224315,1194.0,197.0
|
||||||
|
maze100x100,A*,2.7651999989757314,1194.0,197.0
|
||||||
|
maze100x100,A*,2.860200002032798,1194.0,197.0
|
||||||
|
maze100x100,A*,2.8369999999995343,1194.0,197.0
|
||||||
|
maze100x100,A*,2.906600002461346,1194.0,197.0
|
||||||
|
maze100x100,A*,2.7929999996558763,1194.0,197.0
|
||||||
|
maze100x100,A*,3.06319999799598,1194.0,197.0
|
||||||
|
maze100x100,A*,2.834499999153195,1194.0,197.0
|
||||||
|
maze100x100,A*,2.7511999978742097,1194.0,197.0
|
||||||
|
maze100x100,A*,2.793700001348043,1194.0,197.0
|
||||||
|
maze100x100(среднее),A*,2.8183300000819145,1194.0,197.0
|
||||||
|
maze_empty,A*,13.580099999671802,5328.0,158.0
|
||||||
|
maze_empty,A*,13.65030000306433,5328.0,158.0
|
||||||
|
maze_empty,A*,13.666799997736234,5328.0,158.0
|
||||||
|
maze_empty,A*,14.009900001838105,5328.0,158.0
|
||||||
|
maze_empty,A*,13.549700001021847,5328.0,158.0
|
||||||
|
maze_empty,A*,13.690499999938766,5328.0,158.0
|
||||||
|
maze_empty,A*,13.920800000050804,5328.0,158.0
|
||||||
|
maze_empty,A*,13.680399999429936,5328.0,158.0
|
||||||
|
maze_empty,A*,13.70409999799449,5328.0,158.0
|
||||||
|
maze_empty,A*,13.471199999912642,5328.0,158.0
|
||||||
|
maze_empty(среднее),A*,13.692380000065896,5328.0,158.0
|
||||||
|
maze_no_path,A*,2.5481999982730485,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.8395000008458737,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.7317999993101694,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.7791000029537827,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.718199997616466,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.6510000025155023,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.674000003025867,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.6954999993904494,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.705599999899277,1245.0,0.0
|
||||||
|
maze_no_path,A*,2.7092999989690725,1245.0,0.0
|
||||||
|
maze_no_path(среднее),A*,2.705220000279951,1245.0,0.0
|
||||||
|
maze10x10,Dijkstra,0.0546999981452245,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0766999983170535,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0564999972993973,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.055399999837391,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0901999992493074,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0636000004305969,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0642000013613142,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0633000017842277,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.1010999985737726,25.0,16.0
|
||||||
|
maze10x10,Dijkstra,0.0564000001759268,25.0,16.0
|
||||||
|
maze10x10(среднее),Dijkstra,0.0682099995174212,25.0,16.0
|
||||||
|
maze50x50,Dijkstra,1.7924999992828816,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.7590999996173196,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.8786000000545755,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.80720000207657,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.840500000980683,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.7653000031714328,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.9654999996419065,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.79049999860581,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.797400000214111,972.0,176.0
|
||||||
|
maze50x50,Dijkstra,1.7621000006329268,972.0,176.0
|
||||||
|
maze50x50(среднее),Dijkstra,1.8158700004278217,972.0,176.0
|
||||||
|
maze100x100,Dijkstra,3.954100000555627,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.249900001013884,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.330399999162182,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.545499999949243,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.328899998654379,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.53189999825554,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.320200001529884,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.45179999951506,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.341399999248097,2345.0,197.0
|
||||||
|
maze100x100,Dijkstra,4.510700000537327,2345.0,197.0
|
||||||
|
maze100x100(среднее),Dijkstra,4.356479999842122,2345.0,197.0
|
||||||
|
maze_empty,Dijkstra,11.241200001677498,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.333599999488795,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.416299999837063,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.310300000332065,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.522700002387865,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.251799998717615,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.823299999377925,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.53350000095088,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.488299998745788,5328.0,158.0
|
||||||
|
maze_empty,Dijkstra,11.370600001100684,5328.0,158.0
|
||||||
|
maze_empty(среднее),Dijkstra,11.429160000261618,5328.0,158.0
|
||||||
|
maze_no_path,Dijkstra,2.119600001606159,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.07120000050054,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.1706000006815884,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.152000000933185,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.309299998159986,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.229900001111673,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.0933000014338177,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.175500001612818,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.386500000284286,1245.0,0.0
|
||||||
|
maze_no_path,Dijkstra,2.2796000012021977,1245.0,0.0
|
||||||
|
maze_no_path(среднее),Dijkstra,2.198750000752625,1245.0,0.0
|
||||||
|
BIN
stepushovgs/labyrinth/docs/data/img/100x100.pdf
Normal file
BIN
stepushovgs/labyrinth/docs/data/img/100x100.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/labyrinth/docs/data/img/10x10.pdf
Normal file
BIN
stepushovgs/labyrinth/docs/data/img/10x10.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/labyrinth/docs/data/img/50x50.pdf
Normal file
BIN
stepushovgs/labyrinth/docs/data/img/50x50.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/labyrinth/docs/data/img/empty.pdf
Normal file
BIN
stepushovgs/labyrinth/docs/data/img/empty.pdf
Normal file
Binary file not shown.
BIN
stepushovgs/labyrinth/docs/data/img/no_path.pdf
Normal file
BIN
stepushovgs/labyrinth/docs/data/img/no_path.pdf
Normal file
Binary file not shown.
745
stepushovgs/labyrinth/docs/data/main.ipynb
Normal file
745
stepushovgs/labyrinth/docs/data/main.ipynb
Normal file
File diff suppressed because one or more lines are too long
183
stepushovgs/labyrinth/docs/Отчёт.md
Normal file
183
stepushovgs/labyrinth/docs/Отчёт.md
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
## Описание работы
|
||||||
|
Схема реализованных классов:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
class TextFileMazeBuilder {
|
||||||
|
+buildFromFile(filename): Maze
|
||||||
|
}
|
||||||
|
class Maze {
|
||||||
|
-cells: Cell[]
|
||||||
|
-width: int
|
||||||
|
-height: int
|
||||||
|
-start: Cell
|
||||||
|
-exit: Cell
|
||||||
|
+getCell(x,y): Cell
|
||||||
|
+getNeighbors(cell): List~Cell~
|
||||||
|
}
|
||||||
|
|
||||||
|
class Cell {
|
||||||
|
-x: int
|
||||||
|
-y: int
|
||||||
|
-isWall: bool
|
||||||
|
-isStart: bool
|
||||||
|
-isExit: bool
|
||||||
|
-value: int
|
||||||
|
+isPassable(): bool
|
||||||
|
+getXY(): tuple[int, int]
|
||||||
|
+toStr(): str
|
||||||
|
}
|
||||||
|
|
||||||
|
class MazeBuilder {
|
||||||
|
<<interface>>
|
||||||
|
+buildFromFile(filename): Maze
|
||||||
|
}
|
||||||
|
|
||||||
|
class PathFindingStrategy {
|
||||||
|
<<interface>>
|
||||||
|
+name(): str
|
||||||
|
+findPath(maze, start, exit): tuple[list[tuple[int, int]], int]
|
||||||
|
}
|
||||||
|
|
||||||
|
class BFS {
|
||||||
|
+findPath(maze, start, exit): tuple[list[tuple[int, int]], int]
|
||||||
|
}
|
||||||
|
class DFS {
|
||||||
|
+findPath(maze, start, exit): tuple[list[tuple[int, int]], int]
|
||||||
|
}
|
||||||
|
class AStar {
|
||||||
|
+findPath(maze, start, exit): tuple[list[tuple[int, int]], int]
|
||||||
|
+heuristic(a, b): int
|
||||||
|
}
|
||||||
|
class Dijkstra {
|
||||||
|
+findPath(maze, start, exit): tuple[list[tuple[int, int]], int]
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchStats {
|
||||||
|
-timeMs: float
|
||||||
|
-visitedCells: int
|
||||||
|
-pathLength: int
|
||||||
|
-path: list~Cell~
|
||||||
|
}
|
||||||
|
|
||||||
|
class MazeSolver {
|
||||||
|
-Maze maze
|
||||||
|
-PathFindingStrategy strategy
|
||||||
|
-Observer observer
|
||||||
|
+strategyName: str
|
||||||
|
+setStrategy(strategy)
|
||||||
|
+solve(): SearchStats
|
||||||
|
}
|
||||||
|
|
||||||
|
class Observer {
|
||||||
|
<<interface>>
|
||||||
|
+update(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConsoleView {
|
||||||
|
+update(event)
|
||||||
|
+render(maze, player_position, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
-event: str
|
||||||
|
-maze: Maze
|
||||||
|
-player_position: tuple[int,int]
|
||||||
|
-path: list~Cell~
|
||||||
|
}
|
||||||
|
|
||||||
|
MazeBuilder <|.. TextFileMazeBuilder
|
||||||
|
MazeBuilder --> Maze : creates
|
||||||
|
PathFindingStrategy <|.. BFS
|
||||||
|
PathFindingStrategy <|.. DFS
|
||||||
|
PathFindingStrategy <|.. AStar
|
||||||
|
PathFindingStrategy <|.. Dijkstra
|
||||||
|
MazeSolver --> PathFindingStrategy : uses
|
||||||
|
MazeSolver --> Maze : uses
|
||||||
|
Maze --> Cell : uses
|
||||||
|
MazeSolver --> SearchStats : return
|
||||||
|
Observer <|.. ConsoleView
|
||||||
|
ConsoleView --> Event : get
|
||||||
|
MazeSolver --> Observer : notifies
|
||||||
|
```
|
||||||
|
1. Листинги ключевых классов (можно выборочно) или ссылка на репозиторий.
|
||||||
|
- Классы `Cell` и `Maze` представлены в папке `source/classes/`
|
||||||
|
- Реализации интерфейса `Builder` и класса `TextFileMazeBuilder` находятся в `source/builder/`
|
||||||
|
- Реализации интерфейса `Observer` и класса `ConsoleView` находятся в `source/observer/`
|
||||||
|
- Интерфейс `strategy`, класс `MazeSolver` и реализации алгоритмов BFS, DFS, A*, Дейкстра находятся в папке `source/strategy/`
|
||||||
|
## Результаты экспериментов
|
||||||
|
Все результаты находятся в `/data/cvs/banchmark.csv`, тесты запускаются через файл `benchmark.ipynb`. Лабиринты, на которых проходили тесты, находятся в директори `mazes/benchmarks/`
|
||||||
|
Проведём 10 замеров и отобразим результаты на графиках (пунктиром отмечены среднее значение)
|
||||||
|
![[10x10.pdf]]
|
||||||
|
![[50x50.pdf]]
|
||||||
|
![[100x100.pdf]]
|
||||||
|
![[empty.pdf]]
|
||||||
|
![[no_path.pdf]]
|
||||||
|
|
||||||
|
Заполним таблицу для количества посещённых клеток для каждого алгоритма:
|
||||||
|
|
||||||
|
| Лабиринт | BFS | DFS | A* | Дейкстра |
|
||||||
|
| :------------: | :--: | :--: | :--: | :------: |
|
||||||
|
| $10\times10$ | 25 | 24 | 24 | 25 |
|
||||||
|
| $50\times50$ | 972 | 920 | 763 | 972 |
|
||||||
|
| $100\times100$ | 2345 | 2609 | 1194 | 2345 |
|
||||||
|
| Пустой | 5328 | 5328 | 5328 | 5328 |
|
||||||
|
| Без выхода | 1245 | 1245 | 1245 | 1245
|
||||||
|
|
||||||
|
## Анализ результатов
|
||||||
|
- **DFS** быстрее на большинстве лабиринтов, но путь может быть неоптимальным
|
||||||
|
В качестве демонстрации, сравним работу DFS и BFS на небольшом пустом лабиринте:
|
||||||
|
```
|
||||||
|
BFS
|
||||||
|
Путь найден:
|
||||||
|
#####################################
|
||||||
|
#S #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#. #
|
||||||
|
#..................................E#
|
||||||
|
#####################################
|
||||||
|
time: 0.8261000002676155 ms
|
||||||
|
visited cells: 315
|
||||||
|
path length: 43
|
||||||
|
```
|
||||||
|
```
|
||||||
|
DFS
|
||||||
|
Путь найден:
|
||||||
|
#####################################
|
||||||
|
#S..................................#
|
||||||
|
# .#
|
||||||
|
#...................................#
|
||||||
|
#. #
|
||||||
|
#...................................#
|
||||||
|
# .#
|
||||||
|
#...................................#
|
||||||
|
#. #
|
||||||
|
#..................................E#
|
||||||
|
#####################################
|
||||||
|
time: 0.6825999989814591 ms
|
||||||
|
visited cells: 315
|
||||||
|
path length: 179
|
||||||
|
```
|
||||||
|
Как видно по примеру DFS нашёл путь быстрее (0.68 против 0.82 мс), но длина найденного маршрута 179 клеток, в то время как путь, найденный BFS состоит из 43 клеток.
|
||||||
|
#### A*:
|
||||||
|
- По таблице видно, что A* проходит меньше всего клеток. Это происходит, так как идея алгоритма в том что он отдаёт приоритет клеткам, которые ближе к цели.
|
||||||
|
- На практике медленнее DFS из-за операций с кучей (O(log n) на каждый шаг)
|
||||||
|
|
||||||
|
#### Dijkstra:
|
||||||
|
- По сложности аналогичен BFS для лабиринтов без весов, но медленнее BFS из-за приоритетной очереди.
|
||||||
|
- Имеет смысл на взвешенных графах
|
||||||
|
|
||||||
|
## Выводы
|
||||||
|
Использование ООП и паттернов дало:
|
||||||
|
- расширяемость - лёгкость добавления нового алгоритма поиска без изменения текущей структуры и существующих классов
|
||||||
|
- гибкость - можно менять алгоритмы поиска, конструкторы лабиринтов и способы отображения так же без изменения уже существующих
|
||||||
|
- Лёгкость тестирования - можно тестировать каждый элемент независимо
|
||||||
|
Без этого было бы сложно внедрять новые реализации классов, способы отображения или создания лабиринта или изменять существующие алгоритмы.
|
||||||
|
Но реализация интерфейсов и унификация классов увеличили объём кода и так же наложили ограничения на обрабатываемые данные.
|
||||||
|
|
||||||
|
По скорости лучшим по большинству тестов стал DFS. Второй по скорости BFS, так же он находит самый короткий путь, но при усложнении лабиринта(увеличении развилок и размера) начинает проигрывать A*.
|
||||||
103
stepushovgs/labyrinth/mazes/benchmarks/maze100x100.txt
Normal file
103
stepushovgs/labyrinth/mazes/benchmarks/maze100x100.txt
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
#######################################################################################################
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
### # ##### # # # ############# ######### ### ### # # # ### # # # # # # ####### ##### ##### # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ##### # ##### ### ### ### # ##### # ####### ##### ### ##### ### ####### # # ####### ### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### ### ### ##### # ####### ### ### # ##### ##### # ########### ### ### ##### ### # ### # # # # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### # ### # ######### ##### ### # ### # ### ##### ### ### # ### # # # ### # # ##### # ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ### ### # # ### # # ####### # # # ### # ### # # # ####### # # ##### ### ### ### # ##### ### # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # ### ### # ##### # # ##### ### # ##### # ##### ##### ### # # ####### ##### # # # # # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ##### ### # ### # ### # # ### ##### ####### ### ##### ### ### # # # # # # # ######### # # ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### ### ### # ############# ### # # ### ############### # ##### # ##### ### # # ########### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ##### # ####### ##### ##### ### ### # ### ### ### ####### ##### # # ##### ##### # # # # ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # # ### ##### # # # # ##### ##### ##### ##### # ##### # ### ##### ### ### ### ### ### ########### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ####### # ### # # ##### # # ### # ########### ##### # # ### # ### # # # # ##### # ### # ####### # ###
|
||||||
|
# # # # # # # S # # # # # # # # # # # # # # #
|
||||||
|
### # ####### # ##### ##### ### # ### ### ####### # # # # ### ### # ######### # ### ### ### # # ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ########### # ### # # # # # ### ########### # # # ####### ### # ##### ### ### ### # ### ####### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ##### # # ####### ### ##### # # ######### # ##### ### # ##### ########### # # # # # ### # # ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### # ### # # # # # ### ##### ### ### ##### ##### ### # ### # ### ####### # # ### ####### # #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ### ### ### ##### # # ##### ### # ### # # ### ### ##### ####### ####### # ##### ### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # ##### # # # # # # # ### # ### ##### ### ### ######### # # # ##### # # ### ##### ### # # ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # ####### ### ##### # ##### ####### # # ### ######### ### # # # ########### ####### ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### # ### # # # ##### ### # ### # # ####### ### # ##### # ##### ##### ### # # ####### ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ############### # # ### # ##### ### ### ### # # # ### ### # # ### # # ### ##### ### ### ####### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # ####### # ##### ### ### ##### # ####### ######### # ### # ####### # ######### # # ######### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### # ### # ### ##### # ##### # ### # ### # # # # ##### # # # ############# ####### ### # ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ##### ### # ### ##### ### # ### # # # # ##### # ### # # # # # # ### # # # ### ######### ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ##### ### ##### ##### ####### ### ########### # # # ### # # ### ####### # # # # ######### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ### ### ### ### # ##### # # ####### # # # # ####### ####### ##### ##### ####### # ##### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ####### # ##### # # ### ##### ### # ####### ### ### # ##### # ### # ### ##### # ### # # # # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### # # # ##### ##### # # ####### # # ### ####### ### # ##### ### # # # ####### # # ### ### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### # ### # # ############### # ##### ############# # ##### # ### # ### # # ### # # # # ######### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ######### # ### # ####### # ####### # # # ### # ### ### # ##### ### # ##### ############### ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ### ### # ####### # ### # ### # ### # ### ##### ##### ##### ### ### # # # # # # ##### ##### ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### # ### ####### ### ####### # ### ##### # # ####### ##### ### ### # ##### # ####### # # # ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ##### # # ##### # # ### # ##### # ### # # ### ### # ### ########### ### # # ### ### ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### ### ##### ### # ####### ### ##### ### # ######### ##### ### ### ##### ####### ##### ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
########### ##### ##### # ### ### ### # ####### # # ### ### ### # # # # # ### # ##### # # # ### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ##### # ### # # # # # ### # # # ##### # ### ### # # ### ##### ####### ### # # ### ######### # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ####### # ### ### ##### ##### # ### ### ### ### # ##### # ### # # # ##### # ### ### # ######### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # ### # ##### ####### # ##### ##### ##### # # # # # ### # # ######### # ### # ####### # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ############# ### ### ##### ######### # ### ####### # ### # # ####### # ### ##### ### #######
|
||||||
|
# # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### # # # ### ##### # # ### ############### ### # # # ##### # # ##### ##### # ### ##### ##### # ###
|
||||||
|
# # # # # # # # # # # # # # # E # # # # # # # # #
|
||||||
|
# # ### ##### # ##### ### # # # ### # ### # ######### # # ##### ####### ####### ##### ####### # #######
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ####### ### # # # ##### ######### ### ##### ####### # # # # # # # # # # ### # ### # ### # ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ####### # # ### # ### ####### # ### # # ### ####### ####### ### ### # ########### # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ####### ######### ##### # # ### ### ### # ### # # # ##### ### # ##### ### # # # ### ###########
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # # # # # # ##### ##### ##### # ##### # ##### # # ### # # # # ######### ########### # ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### ####### ### ### # ### ######### ##### ##### ####### # # ##### # # # ### # ######### ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ####### # ### # ### ######### # ### # # ### # # # # ##### ### # # ##### ### ######### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### ### # ######### ### # ### ### # ### # ########### ### ### # ### # # ### ### ######### # ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # # ### # # # ##### ### # ### ### # ##### ### # ### ##### ##### ####### ##### # ### ### ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ##### # # ##### ### # # ##### ##### # # ######### ### ### ##### ### ### # ### ##### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### # ### # ##### # # ####### # ### ### # ### # ### # # ### ### # # ##### # # ### ### # # # ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
#######################################################################################################
|
||||||
6
stepushovgs/labyrinth/mazes/benchmarks/maze10x10.txt
Normal file
6
stepushovgs/labyrinth/mazes/benchmarks/maze10x10.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
S # #####
|
||||||
|
## # # E#
|
||||||
|
# # ###
|
||||||
|
### ## # #
|
||||||
|
# #
|
||||||
|
##########
|
||||||
53
stepushovgs/labyrinth/mazes/benchmarks/maze50x50.txt
Normal file
53
stepushovgs/labyrinth/mazes/benchmarks/maze50x50.txt
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#####################################################
|
||||||
|
# S # # # # # # # # #
|
||||||
|
####### ##### # ##### # # ### ### ### ### ##### # ###
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# ##### # ####### ##### ### ####### ### ### # # # # #
|
||||||
|
# # # # # # # # # # # # # # # #
|
||||||
|
# ### # ##### # # # # ##### # # # ##### # ### ### ###
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# ### # # ### # ### # ### # # ######### ##### # ### #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
### # ### ####### ### # ### ### ####### # ### ### # #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# ### # # # # # ##### ### # ### ### # ######### #####
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ############# # # ### ##### ##### ### ##### ### # #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
### # # # ########### ##### # ### ### ######### ### #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ### # ####### # ##### # ### ### ####### # # # ### #
|
||||||
|
# # # # # # # # # # # # # # # #
|
||||||
|
# # # ### # # ####### # ### ### ### ##### ### #######
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
### ### ##### # # ### ### ### # ### # ######### ### #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# # # ### ##### # # # # ########### # ### # # # # ###
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# # # ############# ##### ##### ##### ### # ##### # #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ##### ### ##### # # # ### # ### ####### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
### ### # ######### # ### # ### # # # # ### ##### # #
|
||||||
|
# # # # # # # # # # #
|
||||||
|
### # # ####### # ### ############# # # # ### ### # #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
### # ######### ####### # ### # # # ### ##### ##### #
|
||||||
|
# # # # # E # # # # # #
|
||||||
|
# ### ##### ### # ### ### # ####### # ##### # #######
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # ##### # ####### ### # ### ##### # # # ###
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
####### ##### # ### ### # ##### ##### ### ##### ### #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# # # # # # # # ##### ### # # # ### ### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
# ############# ### ### # ### # # ### ### ### ##### #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# # # # # # ### ### # ##### ### ### ### # ### ### # #
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
# ##### ##### ### ########### ####### ##### ### #####
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
# # # ##### # # ### # ### # # # # ### ### # ##### ###
|
||||||
|
# # # # # # # # # #
|
||||||
|
#####################################################
|
||||||
50
stepushovgs/labyrinth/mazes/benchmarks/maze_empty.txt
Normal file
50
stepushovgs/labyrinth/mazes/benchmarks/maze_empty.txt
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#################################################################################################################
|
||||||
|
#S #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# E#
|
||||||
|
#################################################################################################################
|
||||||
53
stepushovgs/labyrinth/mazes/benchmarks/maze_no_path.txt
Normal file
53
stepushovgs/labyrinth/mazes/benchmarks/maze_no_path.txt
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#####################################################
|
||||||
|
# S # # # # # # # # #
|
||||||
|
####### ##### # ##### # # ### ### ### ### ##### # ###
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# ##### # ####### ##### ### ####### ### ### # # # # #
|
||||||
|
# # # # # # # # # # # # # # # #
|
||||||
|
# ### # ##### # # # # ##### # # # ##### # ### ### ###
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# ### # # ### # ### # ### # # ######### ##### # ### #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
### # ### ####### ### # ### ### ####### # ### ### # #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# ### # # # # # ##### ### # ### ### # ######### #####
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ############# # # ### ##### ##### ### ##### ### # #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
### # # # ########### ##### # ### ### ######### ### #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ### # ####### # ##### # ### ### ####### # # # ### #
|
||||||
|
# # # # # # # # # # # # # # # #
|
||||||
|
# # # ### # # ####### # ### ### ### ##### ### #######
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
### ### ##### # # ### ### ### # ### # ######### ### #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# # # ### ##### # # # # ########### # ### # # # # ###
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# # # ############# ##### ##### ##### ### # ##### # #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# ##### ### ##### # # # ### # ### ####### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
### ### # ######### # ### # ### # # # # ### ##### # #
|
||||||
|
# # # # # # # # # # #
|
||||||
|
### # # ####### # ### ############# # # # ### ### # #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
### # ######### ####### # ######### ### ##### ##### #
|
||||||
|
# # # # # E # # # # # #
|
||||||
|
# ### ##### ### # ### ### # ####### # ##### # #######
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # ##### # ####### ### # ### ##### # # # ###
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
####### ##### # ### ### # ##### ##### ### ##### ### #
|
||||||
|
# # # # # # # # # # # # # # #
|
||||||
|
# # # # # # # # ##### ### # # # ### ### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # #
|
||||||
|
# ############# ### ### # ### # # ### ### ### ##### #
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# # # # # # ### ### # ##### ### ### ### # ### ### # #
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
# ##### ##### ### ########### ####### ##### ### #####
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
# # # ##### # # ### # ### # # # # ### ### # #########
|
||||||
|
# # # # # # # # # #
|
||||||
|
#####################################################
|
||||||
6
stepushovgs/labyrinth/mazes/tests/test_lab.txt
Normal file
6
stepushovgs/labyrinth/mazes/tests/test_lab.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
S # #####
|
||||||
|
## # # E#
|
||||||
|
# # ###
|
||||||
|
### ## # #
|
||||||
|
# #
|
||||||
|
##########
|
||||||
103
stepushovgs/labyrinth/mazes/tests/test_lab100.txt
Normal file
103
stepushovgs/labyrinth/mazes/tests/test_lab100.txt
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
#######################################################################################################
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
### # ##### # # # ############# ######### ### ### # # # ### # # # # # # ####### ##### ##### # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ##### # ##### ### ### ### # ##### # ####### ##### ### ##### ### ####### # # ####### ### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### ### ### ##### # ####### ### ### # ##### ##### # ########### ### ### ##### ### # ### # # # # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### # ### # ######### ##### ### # ### # ### ##### ### ### # ### # # # ### # # ##### # ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ### ### # # ### # # ####### # # # ### # ### # # # ####### # # ##### ### ### ### # ##### ### # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # ### ### # ##### # # ##### ### # ##### # ##### ##### ### # # ####### ##### # # # # # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ##### ### # ### # ### # # ### ##### ####### ### ##### ### ### # # # # # # # ######### # # ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### ### ### # ############# ### # # ### ############### # ##### # ##### ### # # ########### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ##### # ####### ##### ##### ### ### # ### ### ### ####### ##### # # ##### ##### # # # # ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # # ### ##### # # # # ##### ##### ##### ##### # ##### # ### ##### ### ### ### ### ### ########### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ####### # ### # # ##### # # ### # ########### ##### # # ### # ### # # # # ##### # ### # ####### # ###
|
||||||
|
# # # # # # # S # # # # # # # # # # # # # # #
|
||||||
|
### # ####### # ##### ##### ### # ### ### ####### # # # # ### ### # ######### # ### ### ### # # ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ########### # ### # # # # # ### ########### # # # ####### ### # ##### ### ### ### # ### ####### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ##### # # ####### ### ##### # # ######### # ##### ### # ##### ########### # # # # # ### # # ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### # ### # # # # # ### ##### ### ### ##### ##### ### # ### # ### ####### # # ### ####### # #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # ### ### ### ##### # # ##### ### # ### # # ### ### ##### ####### ####### # ##### ### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # ##### # # # # # # # ### # ### ##### ### ### ######### # # # ##### # # ### ##### ### # # ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # ####### ### ##### # ##### ####### # # ### ######### ### # # # ########### ####### ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### # ### # # # ##### ### # ### # # ####### ### # ##### # ##### ##### ### # # ####### ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ############### # # ### # ##### ### ### ### # # # ### ### # # ### # # ### ##### ### ### ####### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # ####### # ##### ### ### ##### # ####### ######### # ### # ####### # ######### # # ######### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### # ### # ### ##### # ##### # ### # ### # # # # ##### # # # ############# ####### ### # ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ##### ### # ### ##### ### # ### # # # # ##### # ### # # # # # # ### # # # ### ######### ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ##### ### ##### ##### ####### ### ########### # # # ### # # ### ####### # # # # ######### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ### ### ### ### # ##### # # ####### # # # # ####### ####### ##### ##### ####### # ##### ### ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ####### # ##### # # ### ##### ### # ####### ### ### # ##### # ### # ### ##### # ### # # # # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### # # # ##### ##### # # ####### # # ### ####### ### # ##### ### # # # ####### # # ### ### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### # ### # # ############### # ##### ############# # ##### # ### # ### # # ### # # # # ######### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ######### # ### # ####### # ####### # # # ### # ### ### # ##### ### # ##### ############### ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ### ### # ####### # ### # ### # ### # ### ##### ##### ##### ### ### # # # # # # ##### ##### ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### # ### ####### ### ####### # ### ##### # # ####### ##### ### ### # ##### # ####### # # # ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ##### # # ##### # # ### # ##### # ### # # ### ### # ### ########### ### # # ### ### ##### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### ### ##### ### # ####### ### ##### ### # ######### ##### ### ### ##### ####### ##### ### ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
########### ##### ##### # ### ### ### # ####### # # ### ### ### # # # # # ### # ##### # # # ### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ##### # ### # # # # # ### # # # ##### # ### ### # # ### ##### ####### ### # # ### ######### # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ####### # ### ### ##### ##### # ### ### ### ### # ##### # ### # # # ##### # ### ### # ######### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # ### # ##### ####### # ##### ##### ##### # # # # # ### # # ######### # ### # ####### # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ############# ### ### ##### ######### # ### ####### # ### # # ####### # ### ##### ### #######
|
||||||
|
# # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### # # # ### ##### # # ### ############### ### # # # ##### # # ##### ##### # ### ##### ##### # ###
|
||||||
|
# # # # # # # # # # # # # # # E # # # # # # # # #
|
||||||
|
# # ### ##### # ##### ### # # # ### # ### # ######### # # ##### ####### ####### ##### ####### # #######
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### ####### ### # # # ##### ######### ### ##### ####### # # # # # # # # # # ### # ### # ### # ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ####### # # ### # ### ####### # ### # # ### ####### ####### ### ### # ########### # ### #####
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ####### ######### ##### # # ### ### ### # ### # # # ##### ### # ##### ### # # # ### ###########
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
##### # # # # # # # # # ##### ##### ##### # ##### # ##### # # ### # # # # ######### ########### # ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # ### ### ####### ### ### # ### ######### ##### ##### ####### # # ##### # # # ### # ######### ### # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ### ### ####### # ### # ### ######### # ### # # ### # # # # ##### ### # # ##### ### ######### # # ###
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# ##### ### # ######### ### # ### ### # ### # ########### ### ### # ### # # ### ### ######### # ##### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# # # # # ### # # # ##### ### # ### ### # ##### ### # ### ##### ##### ####### ##### # ### ### ### # # #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ##### # # ##### ### # # ##### ##### # # ######### ### ### ##### ### ### # ### ##### # # ### ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
### # ### # ### # ##### # # ####### # ### ### # ### # ### # # ### ### # # ##### # # ### ### # # # ### #
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
#######################################################################################################
|
||||||
11
stepushovgs/labyrinth/mazes/tests/test_lab2.txt
Normal file
11
stepushovgs/labyrinth/mazes/tests/test_lab2.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#####################################
|
||||||
|
#S #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# #
|
||||||
|
# E#
|
||||||
|
#####################################
|
||||||
23
stepushovgs/labyrinth/mazes/tests/test_lab20x20.txt
Normal file
23
stepushovgs/labyrinth/mazes/tests/test_lab20x20.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#######################
|
||||||
|
# # # # # # #
|
||||||
|
### ### ##### # # # ###
|
||||||
|
# # # # # #
|
||||||
|
# # # ##### ### ##### #
|
||||||
|
# # # # # #
|
||||||
|
##### ### # ######### #
|
||||||
|
# #
|
||||||
|
##### # # ### ####### #
|
||||||
|
# # # # # # #
|
||||||
|
########### # ### ### #
|
||||||
|
# # # # # # # #
|
||||||
|
# ### # # ### # ### ###
|
||||||
|
# # # # # # #
|
||||||
|
# ### ####### # # ### #
|
||||||
|
# # # # #
|
||||||
|
### ####### ### #######
|
||||||
|
# # # #
|
||||||
|
########### # ##### # #
|
||||||
|
# # # # #
|
||||||
|
##### ####### ##### # #
|
||||||
|
# # # #
|
||||||
|
#######################
|
||||||
9
stepushovgs/labyrinth/mazes/tests/test_lab3.txt
Normal file
9
stepushovgs/labyrinth/mazes/tests/test_lab3.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
####################
|
||||||
|
#S #
|
||||||
|
# ########## #
|
||||||
|
# #### #
|
||||||
|
# ######## #
|
||||||
|
# #
|
||||||
|
# ####### #### #
|
||||||
|
# E #
|
||||||
|
####################
|
||||||
9
stepushovgs/labyrinth/mazes/tests/test_labNoPath.txt
Normal file
9
stepushovgs/labyrinth/mazes/tests/test_labNoPath.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
####################
|
||||||
|
#S #
|
||||||
|
# ########## #
|
||||||
|
# #### #
|
||||||
|
# ######## #
|
||||||
|
# #
|
||||||
|
# ####### #######
|
||||||
|
# #E #
|
||||||
|
####################
|
||||||
4
stepushovgs/labyrinth/source/__init__.py
Normal file
4
stepushovgs/labyrinth/source/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .builder import *
|
||||||
|
from .classes import *
|
||||||
|
from .observer import *
|
||||||
|
from .strategy import *
|
||||||
4
stepushovgs/labyrinth/source/builder/__init__.py
Normal file
4
stepushovgs/labyrinth/source/builder/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .builder import MazeBuilder
|
||||||
|
from .text_file_maze_builder import TextFileMazeBuilder
|
||||||
|
|
||||||
|
__all__ = ['MazeBuilder', 'TextFileMazeBuilder']
|
||||||
9
stepushovgs/labyrinth/source/builder/builder.py
Normal file
9
stepushovgs/labyrinth/source/builder/builder.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
from source.classes.maze import Maze
|
||||||
|
|
||||||
|
class MazeBuilder(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def buildFromFile(self, filename: str) -> Maze:
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
from source.classes.maze import Maze, Cell
|
||||||
|
from .builder import MazeBuilder
|
||||||
|
|
||||||
|
|
||||||
|
class TextFileMazeBuilder(MazeBuilder):
|
||||||
|
def buildFromFile(self, filename: str) -> Maze:
|
||||||
|
"""Получает лабиринт из текстового файла"""
|
||||||
|
with open(filename) as f:
|
||||||
|
data = f.read().splitlines()
|
||||||
|
x, y = 0, 0
|
||||||
|
width = len(data[0])
|
||||||
|
height = len(data)
|
||||||
|
|
||||||
|
cells = [[None] * width for _ in range(height)]
|
||||||
|
|
||||||
|
start, c_exit = None, None
|
||||||
|
|
||||||
|
for line in data:
|
||||||
|
x = 0
|
||||||
|
for c in line.strip():
|
||||||
|
if c == 'S':
|
||||||
|
cells[y][x] = Cell(x, y, isStart=True)
|
||||||
|
start = cells[y][x]
|
||||||
|
x += 1
|
||||||
|
elif c == 'E':
|
||||||
|
cells[y][x] = Cell(x, y, isExit=True)
|
||||||
|
c_exit = cells[y][x]
|
||||||
|
x += 1
|
||||||
|
elif c == '#':
|
||||||
|
cells[y][x] = Cell(x, y, isWall=True)
|
||||||
|
x += 1
|
||||||
|
elif c == ' ':
|
||||||
|
cells[y][x] = Cell(x, y)
|
||||||
|
x += 1
|
||||||
|
else:
|
||||||
|
print(f'Обнаружен неизвестный символ({c}) в файле лабиринта\nfilename: {filename}\nОн заменён на стену')
|
||||||
|
cells[y][x] = Cell(x, y, isWall=True)
|
||||||
|
x += 1
|
||||||
|
|
||||||
|
y += 1
|
||||||
|
|
||||||
|
if start == None:
|
||||||
|
raise ValueError(f'В файле лабиринта не обнаружен вход!\nfilename: {filename}')
|
||||||
|
|
||||||
|
if c_exit == None:
|
||||||
|
raise ValueError(f'В файле лабиринта не обнаружен выход!\nfilename: {filename}')
|
||||||
|
|
||||||
|
return Maze(
|
||||||
|
cells=cells,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
start=start,
|
||||||
|
exit_cell=c_exit
|
||||||
|
)
|
||||||
4
stepushovgs/labyrinth/source/classes/__init__.py
Normal file
4
stepushovgs/labyrinth/source/classes/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .cell import Cell
|
||||||
|
from .maze import Maze
|
||||||
|
|
||||||
|
__all__ = ['Cell', 'Maze']
|
||||||
86
stepushovgs/labyrinth/source/classes/cell.py
Normal file
86
stepushovgs/labyrinth/source/classes/cell.py
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
class Cell:
|
||||||
|
"""
|
||||||
|
Клетка лабиринта
|
||||||
|
|
||||||
|
`x, y` - координаты клетки в лабиринте
|
||||||
|
|
||||||
|
`isWall` - Является ли клетка стеной
|
||||||
|
|
||||||
|
`isStart` - Является ли клетка стартом
|
||||||
|
|
||||||
|
`isExit` - Является ли клетка выходом лабиринта
|
||||||
|
|
||||||
|
`value` - Вес клетки
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, isWall=False, isStart=False, isExit=False, value=1):
|
||||||
|
"""
|
||||||
|
Создание клетки лабиринта
|
||||||
|
|
||||||
|
`x` - столбец клетки в лабиринте
|
||||||
|
`y` - строка клетки в лабиринте
|
||||||
|
|
||||||
|
`isWall` - Является ли клетка стеной
|
||||||
|
|
||||||
|
`isStart` - Является ли клетка стартом
|
||||||
|
|
||||||
|
`isExit` - Является ли клетка выходом лабиринта
|
||||||
|
|
||||||
|
`value` - Вес клетки
|
||||||
|
"""
|
||||||
|
self.__x = x
|
||||||
|
self.__y = y
|
||||||
|
self.isWall = isWall
|
||||||
|
self.isStart = isStart
|
||||||
|
self.isExit = isExit
|
||||||
|
self.__value = value
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def isPassable(self) -> bool:
|
||||||
|
"""возвращает `True` для прохода, если клетка не стена"""
|
||||||
|
return not self.isWall
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self) -> int:
|
||||||
|
"""Возвращает координату клетки по оси X"""
|
||||||
|
return self.__x
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self) -> int:
|
||||||
|
"""Возвращает координату клетки по оси Y"""
|
||||||
|
return self.__y
|
||||||
|
|
||||||
|
def getXY(self) -> tuple[int, int]:
|
||||||
|
"""Возвращает кортеж координат в формате `(x, y)`"""
|
||||||
|
return self.__x, self.__y
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> int:
|
||||||
|
"""Возвращает вес клетки"""
|
||||||
|
return self.__value
|
||||||
|
|
||||||
|
def toStr(self) -> str:
|
||||||
|
"""
|
||||||
|
Возвращает строчкое представление клетки
|
||||||
|
|
||||||
|
`#` - Стена
|
||||||
|
|
||||||
|
`S` - Начало лабиринта
|
||||||
|
|
||||||
|
`E` - Конец лабиринта
|
||||||
|
|
||||||
|
` `(пробел) - свободный проход
|
||||||
|
|
||||||
|
`<int>` - Вес клетки
|
||||||
|
"""
|
||||||
|
if self.isWall:
|
||||||
|
return '#'
|
||||||
|
elif self.isStart:
|
||||||
|
return 'S'
|
||||||
|
elif self.isExit:
|
||||||
|
return 'E'
|
||||||
|
else:
|
||||||
|
return ' '
|
||||||
|
|
||||||
|
|
||||||
46
stepushovgs/labyrinth/source/classes/maze.py
Normal file
46
stepushovgs/labyrinth/source/classes/maze.py
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
from .cell import Cell
|
||||||
|
|
||||||
|
class Maze:
|
||||||
|
"""Лабиринт"""
|
||||||
|
def __init__(self, cells, width: int, height: int, start: Cell, exit_cell: Cell):
|
||||||
|
self.cells = cells
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.start = start
|
||||||
|
self.exit = exit_cell
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getCell(self, x: int, y: int) -> Cell:
|
||||||
|
return self.cells[y][x] # строка стобец
|
||||||
|
|
||||||
|
def getNeighbors(self, cell) -> list[Cell]:
|
||||||
|
"""Возвращает список соседних проходимых клеток (вверх, вниз, влево, вправо, если в пределах границ и не стена)."""
|
||||||
|
neighbors = []
|
||||||
|
|
||||||
|
c_x, c_y = cell.getXY()
|
||||||
|
|
||||||
|
if c_y - 1 >= 0 and not self.cells[c_y - 1][c_x].isWall:
|
||||||
|
neighbors.append(self.cells[c_y - 1][c_x])
|
||||||
|
|
||||||
|
if c_y + 1 < self.height and not self.cells[c_y + 1][c_x].isWall:
|
||||||
|
neighbors.append(self.cells[c_y + 1][c_x])
|
||||||
|
|
||||||
|
if c_x - 1 >= 0 and not self.cells[c_y][c_x - 1].isWall:
|
||||||
|
neighbors.append(self.cells[c_y][c_x - 1])
|
||||||
|
|
||||||
|
if c_x + 1 < self.width and not self.cells[c_y][c_x + 1].isWall:
|
||||||
|
neighbors.append(self.cells[c_y][c_x + 1])
|
||||||
|
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
def printer(self):
|
||||||
|
"""Выводит в консоль лабиринт (отладочное)"""
|
||||||
|
for line in self.cells:
|
||||||
|
for c in line:
|
||||||
|
print(c.toStr(), end='')
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
"""Основная информация о лабиринте"""
|
||||||
|
print(f'height: {self.height}\nwidth: {self.width}\nstart: {self.start.getXY()}\nexit: {self.exit.getXY()}\ncount cells: {self.height * self.width}')
|
||||||
0
stepushovgs/labyrinth/source/command/command.py
Normal file
0
stepushovgs/labyrinth/source/command/command.py
Normal file
4
stepushovgs/labyrinth/source/observer/__init__.py
Normal file
4
stepushovgs/labyrinth/source/observer/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .console_view import ConsoleView
|
||||||
|
from .observer import Observer, Event
|
||||||
|
|
||||||
|
__all__ = ['ConsoleView', 'Observer', 'Event']
|
||||||
79
stepushovgs/labyrinth/source/observer/console_view.py
Normal file
79
stepushovgs/labyrinth/source/observer/console_view.py
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
from .observer import Observer, Event
|
||||||
|
from source.classes import Cell, Maze
|
||||||
|
|
||||||
|
class ConsoleView(Observer):
|
||||||
|
|
||||||
|
def update(self, event: Event):
|
||||||
|
"""Вывод состояния лабиринта на экран
|
||||||
|
|
||||||
|
`maze_loaded` - Лабиринт загружен
|
||||||
|
|
||||||
|
`path_found` - Отображает лабиринт и маршрут в нём (символом `*`)
|
||||||
|
|
||||||
|
`move` - Выводит лабиринт и позицию игрока в нём (символом `P`)
|
||||||
|
|
||||||
|
"""
|
||||||
|
if event.event == "path_found":
|
||||||
|
print("Путь найден:")
|
||||||
|
self.render(
|
||||||
|
event.maze,
|
||||||
|
event.player_position,
|
||||||
|
event.path
|
||||||
|
)
|
||||||
|
elif event.event == "move":
|
||||||
|
self.render(
|
||||||
|
event.maze,
|
||||||
|
event.player_position,
|
||||||
|
event.path
|
||||||
|
)
|
||||||
|
elif event.event == "maze_loaded":
|
||||||
|
print("Загружен лабиринт:")
|
||||||
|
self.render(
|
||||||
|
event.maze,
|
||||||
|
event.player_position,
|
||||||
|
event.path
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def render(self, maze:Maze, player_position: tuple[int, int], path: list):
|
||||||
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
|
||||||
|
# Если path содержит объекты Cell, преобразуем в координаты
|
||||||
|
if path and isinstance(path[0], Cell):
|
||||||
|
path_xy = [cell.getXY() for cell in path]
|
||||||
|
else:
|
||||||
|
path_xy = path
|
||||||
|
|
||||||
|
# path_xy = [cell.getXY() for cell in path]
|
||||||
|
|
||||||
|
for line in maze.cells:
|
||||||
|
for c in line:
|
||||||
|
if c.getXY() == player_position:
|
||||||
|
print('P', end='')
|
||||||
|
elif c.toStr() in ["S", "E"]:
|
||||||
|
print(c.toStr(), end='')
|
||||||
|
elif c.getXY() in path_xy:
|
||||||
|
print('.', end='')
|
||||||
|
else:
|
||||||
|
print(c.toStr(), end='')
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
# def render_xy(self, maze: Maze, player_position: tuple[int, int], path: list[tuple[int, int]]):
|
||||||
|
# os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
# # path_xy = [cell.getXY() for cell in path]
|
||||||
|
|
||||||
|
# for line in maze.cells:
|
||||||
|
# for c in line:
|
||||||
|
# if c.getXY() == player_position:
|
||||||
|
# print('P', end='')
|
||||||
|
# elif c.getXY() in path:
|
||||||
|
# print('*', end='')
|
||||||
|
# else:
|
||||||
|
# print(c.toStr(), end='')
|
||||||
|
# print()
|
||||||
21
stepushovgs/labyrinth/source/observer/observer.py
Normal file
21
stepushovgs/labyrinth/source/observer/observer.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
# import os
|
||||||
|
|
||||||
|
from source.classes import Maze
|
||||||
|
|
||||||
|
|
||||||
|
class Event:
|
||||||
|
def __init__(self, event: str, maze: Maze, player_position: tuple[int, int], path):
|
||||||
|
self.event = event
|
||||||
|
self.maze = maze
|
||||||
|
self.player_position = player_position
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
|
||||||
|
class Observer(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def update(self, event: Event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
49
stepushovgs/labyrinth/source/strategy/BFS.py
Normal file
49
stepushovgs/labyrinth/source/strategy/BFS.py
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
|
||||||
|
from source.strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
from source.classes import Maze, Cell
|
||||||
|
|
||||||
|
class BFS(PathFindingStrategy):
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Возвращает название метода"""
|
||||||
|
return "BFS"
|
||||||
|
|
||||||
|
def findPath(self, maze: Maze) -> tuple[list[Cell], int]:
|
||||||
|
start_cell = maze.start
|
||||||
|
exit_cell = maze.exit
|
||||||
|
|
||||||
|
# print(f"Старт: {start_cell.getXY()}")
|
||||||
|
# print(f"Выход: {exit_cell.getXY()}")
|
||||||
|
# print(f"Соседи старта: {[n.getXY() for n in maze.getNeighbors(start_cell)]}")
|
||||||
|
|
||||||
|
queue = deque([start_cell])
|
||||||
|
|
||||||
|
parents = {start_cell.getXY(): Cell(-1, -1)}
|
||||||
|
visited = {start_cell.getXY()}
|
||||||
|
count_visited = 1
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
current = queue.popleft()
|
||||||
|
|
||||||
|
if current.getXY() == exit_cell.getXY():
|
||||||
|
return reconstruct_path(
|
||||||
|
came_from=parents,
|
||||||
|
start=start_cell,
|
||||||
|
end=current
|
||||||
|
), count_visited
|
||||||
|
|
||||||
|
# neigbours = maze.getNeighbors(current)
|
||||||
|
# print(f"для клекти {current.getXY()} соседи: {[neigbour.getXY() for neigbour in neigbours]}")
|
||||||
|
|
||||||
|
for neighbor in maze.getNeighbors(current):
|
||||||
|
neig_xy = neighbor.getXY()
|
||||||
|
|
||||||
|
if neig_xy not in visited:
|
||||||
|
visited.add(neig_xy)
|
||||||
|
parents[neig_xy] = current
|
||||||
|
count_visited += 1
|
||||||
|
queue.append(neighbor)
|
||||||
|
|
||||||
|
return [], count_visited
|
||||||
47
stepushovgs/labyrinth/source/strategy/DFS.py
Normal file
47
stepushovgs/labyrinth/source/strategy/DFS.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
from source.strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
from source.classes import Maze, Cell
|
||||||
|
|
||||||
|
class DFS(PathFindingStrategy):
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Возвращает название метода"""
|
||||||
|
return "DFS"
|
||||||
|
|
||||||
|
def findPath(self, maze: Maze) -> tuple[list[Cell], int]:
|
||||||
|
start_cell = maze.start
|
||||||
|
exit_cell = maze.exit
|
||||||
|
|
||||||
|
# print(f"Старт: {start_cell.getXY()}")
|
||||||
|
# print(f"Выход: {exit_cell.getXY()}")
|
||||||
|
# print(f"Соседи старта: {[n.getXY() for n in maze.getNeighbors(start_cell)]}")
|
||||||
|
|
||||||
|
stack = [start_cell]
|
||||||
|
|
||||||
|
parents = {start_cell.getXY(): Cell(-1, -1)}
|
||||||
|
visited = {start_cell.getXY()}
|
||||||
|
count_visited = 1
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
current = stack.pop()
|
||||||
|
|
||||||
|
if current.getXY() == exit_cell.getXY():
|
||||||
|
return reconstruct_path(
|
||||||
|
came_from=parents,
|
||||||
|
start=start_cell,
|
||||||
|
end=current
|
||||||
|
), count_visited
|
||||||
|
|
||||||
|
# neigbours = maze.getNeighbors(current)
|
||||||
|
# print(f"для клекти {current.getXY()} соседи: {[neigbour.getXY() for neigbour in neigbours]}")
|
||||||
|
|
||||||
|
for neighbor in maze.getNeighbors(current):
|
||||||
|
neig_xy = neighbor.getXY()
|
||||||
|
|
||||||
|
if neig_xy not in visited:
|
||||||
|
visited.add(neig_xy)
|
||||||
|
parents[neig_xy] = current
|
||||||
|
count_visited += 1
|
||||||
|
# new_path = current_path + [neigbour]
|
||||||
|
stack.append(neighbor)
|
||||||
|
|
||||||
|
return [], count_visited
|
||||||
56
stepushovgs/labyrinth/source/strategy/Dijkstra.py
Normal file
56
stepushovgs/labyrinth/source/strategy/Dijkstra.py
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
from heapq import *
|
||||||
|
|
||||||
|
|
||||||
|
from source.strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
from source.classes import Maze, Cell
|
||||||
|
|
||||||
|
|
||||||
|
class Dijkstra(PathFindingStrategy):
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Возвращает название метода"""
|
||||||
|
return "Dijkstra"
|
||||||
|
|
||||||
|
|
||||||
|
def findPath(self, maze: Maze):
|
||||||
|
start_cell = maze.start
|
||||||
|
exit_cell = maze.exit
|
||||||
|
|
||||||
|
queue = []
|
||||||
|
counter = 0 # счётчик для уникальности, чтобы не сравнивать клетки
|
||||||
|
|
||||||
|
heappush(queue, (0, counter, start_cell))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
cost_visited = {start_cell.getXY(): 0}
|
||||||
|
came_from = {start_cell.getXY(): None}
|
||||||
|
visited_count = 1
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
current_cost, _, current_cell = heappop(queue)
|
||||||
|
|
||||||
|
if current_cell.getXY() == exit_cell.getXY():
|
||||||
|
return reconstruct_path(
|
||||||
|
came_from=came_from,
|
||||||
|
start=start_cell,
|
||||||
|
end=current_cell
|
||||||
|
), visited_count
|
||||||
|
|
||||||
|
next_cells = maze.getNeighbors(current_cell)
|
||||||
|
|
||||||
|
for next_cell in next_cells:
|
||||||
|
neighbor_cost = next_cell.value
|
||||||
|
neighbor_cell_xy = next_cell.getXY()
|
||||||
|
|
||||||
|
new_cost = current_cost + neighbor_cost
|
||||||
|
|
||||||
|
if neighbor_cell_xy not in cost_visited or new_cost < cost_visited[neighbor_cell_xy]:
|
||||||
|
heappush(queue, (new_cost, counter, next_cell))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
cost_visited[neighbor_cell_xy] = new_cost
|
||||||
|
came_from[neighbor_cell_xy] = current_cell
|
||||||
|
visited_count += 1
|
||||||
|
|
||||||
|
return [], visited_count
|
||||||
|
|
||||||
12
stepushovgs/labyrinth/source/strategy/__init__.py
Normal file
12
stepushovgs/labyrinth/source/strategy/__init__.py
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
from .strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
from .maze_solver import MazeSolver
|
||||||
|
|
||||||
|
|
||||||
|
from .bfs import BFS
|
||||||
|
from .dfs import DFS
|
||||||
|
from .astar import AStar
|
||||||
|
from .dijkstra import Dijkstra
|
||||||
|
# from .maze_solver import MazeSolver
|
||||||
|
# from .strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
|
||||||
|
__all__ = ['BFS', 'DFS', 'AStar', 'Dijkstra', 'MazeSolver', 'PathFindingStrategy', 'reconstruct_path']
|
||||||
64
stepushovgs/labyrinth/source/strategy/astar.py
Normal file
64
stepushovgs/labyrinth/source/strategy/astar.py
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
from heapq import *
|
||||||
|
|
||||||
|
|
||||||
|
from source.strategy import PathFindingStrategy, reconstruct_path
|
||||||
|
from source.classes import Maze, Cell
|
||||||
|
|
||||||
|
|
||||||
|
class AStar(PathFindingStrategy):
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return "A*"
|
||||||
|
|
||||||
|
def heuristic(self, a: Cell, b: Cell) -> int:
|
||||||
|
x1, y1 = a.getXY()
|
||||||
|
x2, y2 = b.getXY()
|
||||||
|
|
||||||
|
return abs(x1 - x2) + abs(y1 - y2)
|
||||||
|
|
||||||
|
def findPath(self, maze: Maze) -> tuple[list[Cell], int]:
|
||||||
|
start_cell = maze.start
|
||||||
|
exit_cell = maze.exit
|
||||||
|
|
||||||
|
queue = []
|
||||||
|
counter = 0 # счётчик для уникальности, чтобы не сравнивать клетки
|
||||||
|
|
||||||
|
start_h = self.heuristic(start_cell, exit_cell)
|
||||||
|
|
||||||
|
heappush(queue, (start_h, counter, start_cell))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
cost_visited = {start_cell.getXY(): 0}
|
||||||
|
came_from = {start_cell.getXY(): None}
|
||||||
|
visited_count = 1
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
current_cost, _, current_cell = heappop(queue)
|
||||||
|
current_g = cost_visited[current_cell.getXY()]
|
||||||
|
|
||||||
|
if current_cell.getXY() == exit_cell.getXY():
|
||||||
|
return reconstruct_path(
|
||||||
|
came_from=came_from,
|
||||||
|
start=start_cell,
|
||||||
|
end=current_cell
|
||||||
|
), visited_count
|
||||||
|
|
||||||
|
next_cells = maze.getNeighbors(current_cell)
|
||||||
|
|
||||||
|
for next_cell in next_cells:
|
||||||
|
neighbor_cost = next_cell.value
|
||||||
|
neighbor_cell_xy = next_cell.getXY()
|
||||||
|
|
||||||
|
new_cost = current_g + neighbor_cost
|
||||||
|
|
||||||
|
if neighbor_cell_xy not in cost_visited or new_cost < cost_visited[neighbor_cell_xy]:
|
||||||
|
priority = new_cost + self.heuristic(next_cell, exit_cell)
|
||||||
|
|
||||||
|
heappush(queue, (priority, counter, next_cell))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
cost_visited[neighbor_cell_xy] = new_cost
|
||||||
|
came_from[neighbor_cell_xy] = current_cell
|
||||||
|
visited_count += 1
|
||||||
|
|
||||||
|
return [], visited_count
|
||||||
55
stepushovgs/labyrinth/source/strategy/maze_solver.py
Normal file
55
stepushovgs/labyrinth/source/strategy/maze_solver.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
from .strategy import PathFindingStrategy
|
||||||
|
from source.observer import Observer, Event
|
||||||
|
from source.classes import Cell, Maze
|
||||||
|
|
||||||
|
|
||||||
|
class MazeSolver:
|
||||||
|
def __init__(self, maze: Maze, strategy: PathFindingStrategy, observer: Observer):
|
||||||
|
self.maze = maze
|
||||||
|
self.strategy = strategy
|
||||||
|
self.observer = observer
|
||||||
|
|
||||||
|
def strategyName(self) -> str:
|
||||||
|
return self.strategy.name
|
||||||
|
|
||||||
|
def setStrategy(self, strategy: PathFindingStrategy):
|
||||||
|
self.strategy = strategy
|
||||||
|
|
||||||
|
def solve(self):
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
path, visited_cells = self.strategy.findPath(self.maze)
|
||||||
|
finish_time = time.perf_counter()
|
||||||
|
|
||||||
|
self.observer.update(Event(
|
||||||
|
event="path_found",
|
||||||
|
maze=self.maze,
|
||||||
|
player_position=self.maze.exit,
|
||||||
|
path=path
|
||||||
|
))
|
||||||
|
|
||||||
|
return SearchStats(
|
||||||
|
timeMs=(finish_time - start_time) * 1000,
|
||||||
|
visitedCells=visited_cells,
|
||||||
|
pathLength=len(path),
|
||||||
|
path=path
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SearchStats:
|
||||||
|
"""Общая информация о тесте алгоритма"""
|
||||||
|
def __init__(self, timeMs: float, visitedCells: int, pathLength: int, path: list[Cell]):
|
||||||
|
self.timeMs = timeMs
|
||||||
|
self.visitedCells = visitedCells
|
||||||
|
self.pathLength = pathLength
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
"""Вывод информации о тесте в консоль"""
|
||||||
|
print(f'time: {self.timeMs} ms\nvisited cells: {self.visitedCells}\npath length: {self.pathLength}')
|
||||||
|
|
||||||
|
# def toStr(self) -> str:
|
||||||
|
# return f'{self.timeMs} {self.visitedCells} {self.pathLength}'
|
||||||
39
stepushovgs/labyrinth/source/strategy/strategy.py
Normal file
39
stepushovgs/labyrinth/source/strategy/strategy.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
from source.classes import Cell, Maze
|
||||||
|
|
||||||
|
|
||||||
|
class PathFindingStrategy(ABC):
|
||||||
|
"""Интерфейс для семейства алгоритмов поиска пути от старта до выхода."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def findPath(self, maze: Maze) -> tuple[list[tuple[int, int]], int]:
|
||||||
|
"""Возвращающим список координат клеток пути (от старта до выхода включительно) или пустой список, если пути нет и количество посещённых клеток."""
|
||||||
|
pass
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Возвращает название алгоритма"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
# class CellAlgorithm(Cell):
|
||||||
|
# def __init__(self, x: int, y: int, parent: Cell, exitDist: float, isWall=False, isStart=False, isExit=False, value=1):
|
||||||
|
# super().__init__(x, y, isWall, isStart, isExit, value)
|
||||||
|
# self.parent = parent
|
||||||
|
# self.ExitDist = exitDist
|
||||||
|
# self.weight = self.value + exitDist
|
||||||
|
|
||||||
|
|
||||||
|
def reconstruct_path(came_from: dict, start: Cell, end: Cell) -> list[Cell]:
|
||||||
|
"""Восстановление пути по словарю предшественников"""
|
||||||
|
path = []
|
||||||
|
current = end
|
||||||
|
|
||||||
|
# Идём от конца к началу по цепочке came_from
|
||||||
|
while current.getXY() != start.getXY():
|
||||||
|
path.append(current)
|
||||||
|
current = came_from[current.getXY()]
|
||||||
|
|
||||||
|
path.append(start)
|
||||||
|
return path[::-1]
|
||||||
1078
stepushovgs/labyrinth/test.ipynb
Normal file
1078
stepushovgs/labyrinth/test.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user