Изменение иерархии

- добавеление в отлсеживание go.mod
 - перенос хеш таблицы на общий формат хранения данных
 - удаление лишних
This commit is contained in:
GordStep 2026-05-10 12:30:21 +03:00
parent 1b21f97e28
commit 4a214a2843
15 changed files with 492 additions and 303 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

@ -17,3 +17,9 @@ func NewData(name, phone string) *MyData {
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

@ -1,4 +1,4 @@
package gendata
package gen_data
import (
"fmt"

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

@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"os"
ds "source/pkg/data_struct"
)
// HashTable - хеш-таблица с цепочками
@ -19,9 +20,8 @@ type bucket struct {
}
type elementHT struct {
name string
phone string
next *elementHT
data ds.MyData
next *elementHT
}
// NewHashTable - создает новую хеш-таблицу
@ -58,21 +58,21 @@ func (ht *HashTable) GetIndex(name string) int {
// return hash % ht.capacity
// }
func (h *HashTable) Put(name string, phone string) {
func (h *HashTable) Insert(new ds.MyData) {
if h.size >= int(float64(h.capacity)*h.loadFactor) {
h.resize()
}
ind := h.GetIndex(name)
ind := h.GetIndex(new.Name)
buck := h.buckets[ind]
current := buck.head
for current != nil {
if current.name == name {
current.phone = phone
if current.data.Name == new.Name {
current.data.Phone = new.Phone
return
}
@ -80,9 +80,8 @@ func (h *HashTable) Put(name string, phone string) {
}
newHead := &elementHT{
name: name,
phone: phone,
next: buck.head,
data: new,
next: buck.head,
}
buck.head = newHead
@ -97,8 +96,8 @@ func (h *HashTable) Get(name string) (phone string, status bool) {
current := buck.head
for current != nil {
if current.name == name {
return current.phone, true
if current.data.Name == name {
return current.data.Phone, true
}
current = current.next
@ -127,7 +126,7 @@ func (ht *HashTable) resize() {
for _, b := range ht.buckets {
current := b.head
for current != nil {
newHT.Put(current.name, current.phone)
newHT.Insert(current.data)
current = current.next
}
}
@ -145,7 +144,7 @@ func (ht *HashTable) Remove(name string) bool {
return false
}
if buck.head.name == name {
if buck.head.data.Name == name {
buck.head = buck.head.next
ht.size--
return true
@ -155,7 +154,7 @@ func (ht *HashTable) Remove(name string) bool {
current := buck.head.next
for current != nil {
if current.name == name {
if current.data.Name == name {
prev.next = current.next
ht.size--
return true
@ -177,7 +176,7 @@ func (elem *elementHT) ToString() string {
return "nil"
}
return fmt.Sprintf("Имя: %s, Телефон: %s", elem.name, elem.phone)
return elem.ToString()
}
func (ht *HashTable) Print() {
@ -195,8 +194,8 @@ func (ht *HashTable) Print() {
}
}
func (ht *HashTable) listAll() []elementHT {
data := make([]elementHT, ht.size)
func (ht *HashTable) listAll() []ds.MyData {
data := make([]ds.MyData, ht.size)
index := 0
@ -205,10 +204,7 @@ func (ht *HashTable) listAll() []elementHT {
current := buck.head
for current != nil {
data[index] = elementHT{
name: current.name,
phone: current.phone,
}
data[index] = current.data
index++
// fmt.Println(current.name, current.phone)
current = current.next
@ -218,11 +214,11 @@ func (ht *HashTable) listAll() []elementHT {
return data
}
func (ht *HashTable) ListAll() []elementHT {
func (ht *HashTable) ListAll() []ds.MyData {
// fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
data := ht.listAll()
data = QSortElementsHT(data, 0, len(data)-1)
data = ds.QSort(data, 0, len(data)-1)
// for i, el := range data {
// fmt.Printf("[%d]: \"%s\", %d\n", i, el.name, el.phone)

View File

@ -130,3 +130,21 @@ func (ll *LinkedList) listAll() []ds.MyData {
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

@ -5,8 +5,8 @@ import (
"fmt"
"math/rand"
"os"
bst "source/pkg/bin_search_tree"
ds "source/pkg/data_struct"
bst "source/pkg/structures/bin_search_tree"
)
const (

View File

@ -5,7 +5,8 @@ import (
// hash_table "hash-table-task/hash-table"
ht "source/pkg/hash_table"
ds "source/pkg/data_struct"
ht "source/pkg/structures/hash_table"
)
/*
@ -28,6 +29,9 @@ import (
*/
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"
@ -52,20 +56,20 @@ func main() {
// fmt.Printf("Слово %d: %s\n", i+1, word)
// }
hashTable := ht.NewHashTable(8, 0.95)
// hashTable := ht.NewHashTable(8, 0.95)
for i, word := range words {
fmt.Printf("%d : %s\n", i, word)
hashTable.Put(word, 1)
}
// for i, word := range words {
// fmt.Printf("%d : %s\n", i, word)
// hashTable.Put(word, 1)
// }
fmt.Println("\nХеш таблица текста: ")
hashTable.Print()
// fmt.Println("\nХеш таблица текста: ")
// hashTable.Print()
// fmt.Println("Отсортированные ячейки таблицы: ")
// hashTable.PrintSort()
// // fmt.Println("Отсортированные ячейки таблицы: ")
// // hashTable.PrintSort()
fmt.Println("\nСамые часто встречающиеся слова: ")
// fmt.Println("\nСамые часто встречающиеся слова: ")
// hashTable.PrintMostPopularWords(10)
// // hashTable.PrintMostPopularWords(10)
}

View File

@ -5,12 +5,19 @@ import (
"fmt"
"math/rand"
"os"
ds "source/pkg/data_struct"
ll "source/pkg/linked_list"
// dg "source/pkg/gendata"
dg "source/pkg/gen_data"
rs "source/pkg/resulter"
ll "source/pkg/structures/linked_list"
"time"
)
const countNumbers = 64
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++ {
@ -21,6 +28,13 @@ func isInArr(arr []int, length int, target int) bool {
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')
@ -29,59 +43,135 @@ func pressEnterToContinue() {
func main() {
fmt.Println("hello world!")
results := make([]rs.BenchmarkResult, 0, countUsers)
averageInsertTime := 0.
Razdelitel()
fmt.Println("Тестирование вставки:")
var head *ll.LinkedList = nil
arr := make([]int, countNumbers)
for testNum := 0; testNum < countRepeat; testNum++ {
head = nil
var temp int
for i := 0; i < countNumbers; i++ {
// Генерируем уникальное случайное число
for {
temp = rand.Intn(100) // 0 до 99
if !isInArr(arr, i, temp) {
break
}
testData := dg.RecordsShuffled(countUsers)
start := time.Now()
for i := 0; i < countUsers; i++ {
head.Insert(testData[i])
}
arr[i] = temp
elapsed := time.Since(start).Seconds()
averageInsertTime += elapsed
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])
// pressEnterToContinue()
results = append(results, rs.BenchmarkResult{
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: elapsed,
})
}
pressEnterToContinue()
fmt.Printf("\n\nКоличество узлов: %d\n", head.Len())
fmt.Println("\ninorder traversal:")
pressEnterToContinue()
head.PrintAll()
pressEnterToContinue()
tarName := "name_44"
fmt.Printf("\nПоиск '%s' перед удалением: ", tarName)
if found, ok := head.Search(tarName); ok {
fmt.Printf("Найден: %s\n", found)
} else {
fmt.Printf("НЕ найден!\n")
averageInsertTime /= countRepeat
results = append(results, rs.BenchmarkResult{
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: averageInsertTime,
})
for i := 0; i < 6; i++ {
fmt.Println(results[i].ToString())
}
fmt.Printf("\nУдаляем элемент с значением %s:\n", tarName)
Razdelitel()
// fmt.Println("Тестирование Поиска:")
// // results = make([]rs.BenchmarkResult, 0, countUsers)
// averageSearchTime := 0.
head, _ = head.Delete(tarName)
// for testNum := 0; testNum < countRepeat; testNum++ {
// // var head *ll.LinkedList = nil
// // head = dg.RecordsShuffled(countUsers)
fmt.Printf("\nКоличество узлов после удаления: %d\n", head.Len())
// testData := make([]ds.MyData, countRandomSearch)
fmt.Printf("Поиск '%s' после удаления: ", tarName)
if found, ok := head.Search(tarName); ok {
fmt.Printf("ОШИБКА! Все еще существует: %s\n", found)
} else {
fmt.Printf("Успешно удален\n")
// 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
}