Compare commits

...

5 Commits

Author SHA1 Message Date
4a214a2843 Изменение иерархии
- добавеление в отлсеживание go.mod
 - перенос хеш таблицы на общий формат хранения данных
 - удаление лишних
2026-05-10 12:30:21 +03:00
1b21f97e28 Изменение иерархии проекта
- test/ -- папка с файлами для тестов каждой структуры
- pkg/ -- папка с реализациями и вспомогательными модулями
2026-05-09 22:34:03 +03:00
7e045c71e0 Переписан LinkedLIst на Go 2026-05-09 21:11:45 +03:00
9b92dcc206 Переписан тест для BST с C на Go 2026-05-09 20:02:11 +03:00
d616bfe1fb Реализация bst переписана на Go 2026-05-09 19:27:57 +03:00
25 changed files with 1376 additions and 219 deletions

217
.gitignore vendored
View File

@ -1,217 +0,0 @@
# ---> 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

255
stepushovgs/.gitignore vendored
View File

@ -1 +1,256 @@
# ---> 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

View File

@ -1,2 +0,0 @@
.exe
.o

View File

@ -0,0 +1,3 @@
module source
go 1.26.3

View File

@ -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())
}
}

View File

@ -0,0 +1,37 @@
package data_struct
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]
}
}

View File

@ -0,0 +1,41 @@
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()
}
return data
}
func RecordsSorted(count int) []ds.MyData {
data := RecordsShuffled(count)
data = ds.QSort(data, 0, len(data)-1)
return data
}

View File

@ -0,0 +1,36 @@
package resulter
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)
}
// AppendRaw дописывает произвольные строки в CSV
func AppendRaw(rows [][]string) error {
filename := filepath.Join("results", "benchmarks.csv")
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()
return writer.WriteAll(rows) // WriteAll пишет всё сразу
}

View File

@ -0,0 +1,197 @@
package bin_search_tree
import (
"fmt"
ds "source/pkg/data_struct"
)
type BinSearchTree struct {
data ds.MyData
left *BinSearchTree
right *BinSearchTree
}
func NewBinSearchTree(data ds.MyData) *BinSearchTree {
return &BinSearchTree{
data: data,
left: nil,
right: nil,
}
}
func (bst *BinSearchTree) Len() int {
if bst == nil {
return 0
}
return 1 + bst.left.Len() + bst.right.Len()
}
func (bst *BinSearchTree) Minimum() *BinSearchTree {
if bst.left == nil {
return bst
}
return bst.left.Minimum()
}
func (bst *BinSearchTree) Maximum() *BinSearchTree {
if bst.right == nil {
return bst
}
return bst.right.Maximum()
}
func (node *BinSearchTree) PrintNode() {
fmt.Print(node.data.ToString())
}
func (node *BinSearchTree) ToString() string {
if node == nil {
return "nil"
}
return node.data.ToString()
}
func (bst *BinSearchTree) BstInorderTraversal() {
if bst != nil {
bst.left.BstInorderTraversal()
bst.PrintNode()
fmt.Println()
bst.right.BstInorderTraversal()
}
}
func (bst *BinSearchTree) BstPreorderTraversal() {
if bst != nil {
bst.PrintNode()
bst.left.BstPreorderTraversal()
bst.right.BstPreorderTraversal()
}
}
// Search
// Возвращает строковое представление узла
func (bst *BinSearchTree) Search(targetName string) (string, bool) {
node, ok := bst.search(targetName)
if ok {
return node.ToString(), 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 *BinSearchTree) search(targetName string) (*BinSearchTree, 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 (bst *BinSearchTree) Search(targetName string) (string, bool) {
/*
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)
*/
// targetNode, ok := bst.head.search(targetName)
// return targetNode.ToString(), ok
// }
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
}
// 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 (root *BinSearchTree) Delete(targetName string) *BinSearchTree {
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 if root.left != nil && root.right != nil {
temp := root.right.Minimum()
root.data.Name = root.right.Minimum().data.Name
root.data.Phone = root.right.Minimum().data.Phone
// strcpy(root->name, bst_minimum(root->right)->name);
// strcpy(root->phone, bst_minimum(root->right)->phone);
root.right = root.right.Delete(temp.data.Name)
} else {
if root.left != nil {
return root.left
} else if root.right != nil {
return root.right
} else {
return nil
}
}
return root
}
func (bst *BinSearchTree) 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)
}

View File

@ -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
}

View File

@ -0,0 +1,238 @@
package hash_table
import (
"bufio"
"fmt"
"os"
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) 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 (h *HashTable) Get(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) Remove(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.Get(name)
return ok
}
func (elem *elementHT) ToString() string {
if elem == nil {
return "nil"
}
return elem.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())
// }
// }

View File

@ -0,0 +1,37 @@
package hash_table
func QSortElementsHT(arr []elementHT, l, r int) []elementHT {
if l < r {
s := Partition_Hoa(arr, l, r)
arr = QSortElementsHT(arr, l, s)
arr = QSortElementsHT(arr, s+1, r)
}
return arr
}
func Partition_Hoa(arr []elementHT, 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]
}
}

View File

@ -0,0 +1,150 @@
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 {
data ds.MyData
next *LinkedList
}
func NewLinkedList(data ds.MyData) *LinkedList {
return &LinkedList{
data: data,
next: nil,
}
}
func (ll *LinkedList) ToString() string {
return ll.data.ToString()
}
func (ll *LinkedList) Len() int {
if ll == nil {
return 0
}
len := 0
current := ll
for current != nil {
len++
current = current.next
}
return len
}
func (ll *LinkedList) Insert(data ds.MyData) *LinkedList {
newNode := NewLinkedList(data)
if ll == nil {
return newNode
}
current := ll
for current.next != nil {
current = current.next
}
current.next = newNode
return ll
}
func (ll *LinkedList) Search(targetName string) (string, bool) {
current := ll
for current != nil {
if current.data.Name == targetName {
return current.data.Phone, true
}
current = current.next
}
return "", false
}
func (ll *LinkedList) PrintAll() {
current := ll
index := 0
for current != nil {
fmt.Printf("[%d] %s\n", index, current.ToString())
index++
current = current.next
}
}
func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) {
if ll == nil {
return nil, false
}
if ll.data.Name == targetName {
return ll.next, true
}
prev := ll
current := ll.next
for current != nil {
if current.data.Name == targetName {
prev.next = current.next
}
prev = current
current = current.next
}
return ll, false
}
func (ll *LinkedList) listAll() []ds.MyData {
current := ll
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
for current != nil {
if index == ind {
return current.data, true
}
current = current.next
index++
}
return ds.MyData{}, false
}

View File

@ -0,0 +1,90 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"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!")
var head *bst.BinSearchTree = nil
arr := make([]int, countNumbers)
var temp int
for i := 0; i < countNumbers; i++ {
// Генерируем уникальное случайное число
for {
temp = rand.Intn(100) // 0 до 99
if !isInArr(arr, i, temp) {
break
}
}
arr[i] = temp
nameStr := fmt.Sprintf("name_%02d", temp)
phoneStr := fmt.Sprintf("phone_%02d", temp)
data := ds.NewData(nameStr, phoneStr)
head = head.Insert(*data)
fmt.Printf("%d ", arr[i])
}
fmt.Printf("\n\nКоличество узлов: %d\n", head.Len())
pressEnterToContinue()
fmt.Println("\ninorder traversal:")
head.BstInorderTraversal()
tarName := "name_44"
fmt.Printf("\nПоиск '%s' перед удалением: ", tarName)
if found, ok := head.Search(tarName); ok {
fmt.Printf("Найден: %s\n", found)
} else {
fmt.Printf("НЕ найден!\n")
}
fmt.Printf("\nУдаляем элемент с значением %s:\n", tarName)
head = head.Delete(tarName)
fmt.Printf("\nКоличество узлов после удаления: %d\n", head.Len())
fmt.Printf("Поиск '%s' после удаления: ", tarName)
if found, ok := head.Search(tarName); ok {
fmt.Printf("ОШИБКА! Все еще существует: %s\n", found)
} else {
fmt.Printf("Успешно удален\n")
}
fmt.Println("\ninorder traversal after delete:")
head.BstInorderTraversal()
}

View File

@ -0,0 +1,75 @@
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")
hashTable := ht.NewHashTable(8, 0.75)
hashTable.Insert(*ds.NewData("User_0", "Phone_0"))
// Чтение всего файла
// 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)
}

View File

@ -0,0 +1,177 @@
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
dg "source/pkg/gen_data"
rs "source/pkg/resulter"
ll "source/pkg/structures/linked_list"
"time"
)
const (
countUsers = 10000
countRepeat = 5
countRandomSearch = 10000
countNotExitstSearch = 10
countDeletes = 50
)
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!")
results := make([]rs.BenchmarkResult, 0, countUsers)
averageInsertTime := 0.
Razdelitel()
fmt.Println("Тестирование вставки:")
var head *ll.LinkedList = nil
for testNum := 0; testNum < countRepeat; testNum++ {
head = nil
testData := dg.RecordsShuffled(countUsers)
start := time.Now()
for i := 0; i < countUsers; i++ {
head.Insert(testData[i])
}
elapsed := time.Since(start).Seconds()
averageInsertTime += elapsed
results = append(results, rs.BenchmarkResult{
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: elapsed,
})
}
averageInsertTime /= countRepeat
results = append(results, rs.BenchmarkResult{
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: averageInsertTime,
})
for i := 0; i < 6; i++ {
fmt.Println(results[i].ToString())
}
Razdelitel()
// fmt.Println("Тестирование Поиска:")
// // results = make([]rs.BenchmarkResult, 0, countUsers)
// averageSearchTime := 0.
// for testNum := 0; testNum < countRepeat; testNum++ {
// // var head *ll.LinkedList = nil
// // head = dg.RecordsShuffled(countUsers)
// testData := make([]ds.MyData, countRandomSearch)
// for i := 0; i < countRandomSearch; i++ {
// // randInd := rand.Intn(countUsers)
// randInd := rand.Intn(1000) + 9000
// testData[i], _ = head.GetByInd(randInd)
// // fmt.Println(randInd)
// }
// start := time.Now()
// for i := 0; i < countRandomSearch; i++ {
// head.Search(testData[i].Name)
// }
// elapsed := time.Since(start).Seconds()
// averageSearchTime += elapsed
// results = append(results, rs.BenchmarkResult{
// Structure: "Связный список", Mode: "Случайный", Operation: "Поиск", Time: elapsed,
// })
// }
// averageSearchTime /= countRepeat
// results = append(results, rs.BenchmarkResult{
// Structure: "Связный список", Mode: "Случайный", Operation: "Поиск", Time: averageSearchTime,
// })
// for i := 0; i < len(results); i++ {
// fmt.Println(results[i].ToString())
// }
resultsS := runSearchBenchmark(head)
for i := 0; i < len(resultsS); i++ {
fmt.Println(resultsS[i].ToString())
}
// rs.AppendRaw(results)
}
func runSearchBenchmark(head *ll.LinkedList) []rs.BenchmarkResult {
fmt.Println("\n=== Тестирование Поиска ===")
const countRandomSearch = 1000 // уменьшим для поиска
var results []rs.BenchmarkResult
var totalTime float64
// Предварительно собираем имена для поиска
names := make([]string, countUsers)
for i := 0; i < countUsers; i++ {
data, found := head.GetByInd(i)
if found {
names[i] = data.Name
}
}
for testNum := 0; testNum < countRepeat; testNum++ {
// Выбираем случайные имена
searchNames := make([]string, countRandomSearch)
for i := 0; i < countRandomSearch; i++ {
searchNames[i] = names[rand.Intn(countUsers)]
}
start := time.Now()
for _, name := range searchNames {
el, ok := head.Search(name)
if ok {
fmt.Println(el)
}
}
elapsed := time.Since(start).Seconds()
totalTime += elapsed
fmt.Printf(" Тест %d: %.6f сек (%.2f мкс/оп)\n",
testNum+1, elapsed,
elapsed/float64(countRandomSearch)*1_000_000)
}
avgTime := totalTime / float64(countRepeat)
fmt.Printf("Среднее: %.6f сек\n", avgTime)
results = append(results, rs.BenchmarkResult{
Structure: "Связный список",
Mode: "Случайный",
Operation: "Поиск",
Time: avgTime,
})
return results
}