Изменение иерархии проекта

- test/ -- папка с файлами для тестов каждой структуры
- pkg/ -- папка с реализациями и вспомогательными модулями
This commit is contained in:
GordStep 2026-05-09 22:34:03 +03:00
parent 7e045c71e0
commit 1b21f97e28
21 changed files with 479 additions and 56 deletions

View File

@ -1,21 +1,20 @@
package main
package bin_search_tree
import (
"fmt"
ds "source/pkg/data_struct"
)
type BinSearchTree struct {
name string
phone string
data ds.MyData
left *BinSearchTree
right *BinSearchTree
}
func NewBinSearchTree(name, phone string) *BinSearchTree {
func NewBinSearchTree(data ds.MyData) *BinSearchTree {
return &BinSearchTree{
name: name,
phone: phone,
data: data,
left: nil,
right: nil,
}
@ -42,14 +41,14 @@ func (bst *BinSearchTree) Maximum() *BinSearchTree {
}
func (node *BinSearchTree) PrintNode() {
fmt.Printf("Имя: %s, Телефон: %s", node.name, node.phone)
fmt.Print(node.data.ToString())
}
func (node *BinSearchTree) ToString() string {
if node == nil {
return "nil"
}
return fmt.Sprintf("Имя: %s, Телефон: %s", node.name, node.phone)
return node.data.ToString()
}
func (bst *BinSearchTree) BstInorderTraversal() {
@ -93,10 +92,10 @@ func (node *BinSearchTree) search(targetName string) (*BinSearchTree, bool) {
if node == nil {
return nil, false
}
if node.name == targetName {
if node.data.Name == targetName {
return node, true
}
if targetName < node.name {
if targetName < node.data.Name {
return node.left.search(targetName)
}
return node.right.search(targetName)
@ -117,15 +116,15 @@ func (node *BinSearchTree) search(targetName string) (*BinSearchTree, bool) {
// return targetNode.ToString(), ok
// }
func (node *BinSearchTree) Insert(name, phone string) *BinSearchTree {
func (node *BinSearchTree) Insert(data ds.MyData) *BinSearchTree {
if node == nil {
return NewBinSearchTree(name, phone)
} else if name < node.name {
node.left = node.left.Insert(name, phone)
} else if name > node.name {
node.right = node.right.Insert(name, phone)
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.phone = phone // Заменяем существующее значение
node.data.Phone = data.Phone // Заменяем существующее значение
}
return node
}
@ -159,18 +158,18 @@ func (root *BinSearchTree) Delete(targetName string) *BinSearchTree {
return nil
}
if targetName < root.name {
if targetName < root.data.Name {
root.left = root.left.Delete(targetName)
} else if targetName > root.name {
} 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.name = root.right.Minimum().name
root.phone = root.right.Minimum().phone
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.name)
root.right = root.right.Delete(temp.data.Name)
} else {
if root.left != nil {
return root.left

View File

@ -0,0 +1,19 @@
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)
}

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 gendata
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,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,242 @@
package hash_table
import (
"bufio"
"fmt"
"os"
)
// HashTable - хеш-таблица с цепочками
type HashTable struct {
buckets []*bucket
size int
capacity int
loadFactor float64
}
type bucket struct {
head *elementHT
}
type elementHT struct {
name string
phone string
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) Put(name string, phone string) {
if h.size >= int(float64(h.capacity)*h.loadFactor) {
h.resize()
}
ind := h.GetIndex(name)
buck := h.buckets[ind]
current := buck.head
for current != nil {
if current.name == name {
current.phone = phone
return
}
current = current.next
}
newHead := &elementHT{
name: name,
phone: phone,
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.name == name {
return current.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.Put(current.name, current.phone)
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.name == name {
buck.head = buck.head.next
ht.size--
return true
}
prev := buck.head
current := buck.head.next
for current != nil {
if current.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 fmt.Sprintf("Имя: %s, Телефон: %s", elem.name, elem.phone)
}
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() []elementHT {
data := make([]elementHT, ht.size)
index := 0
for ind := 0; ind < ht.capacity; ind++ {
buck := ht.buckets[ind]
current := buck.head
for current != nil {
data[index] = elementHT{
name: current.name,
phone: current.phone,
}
index++
// fmt.Println(current.name, current.phone)
current = current.next
}
}
return data
}
func (ht *HashTable) ListAll() []elementHT {
// fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
data := ht.listAll()
data = QSortElementsHT(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

@ -1,6 +1,6 @@
package main
package hash_table
func QSortElementsHT(arr []LinkedList, l, r int) []LinkedList {
func QSortElementsHT(arr []elementHT, l, r int) []elementHT {
if l < r {
s := Partition_Hoa(arr, l, r)
arr = QSortElementsHT(arr, l, s)
@ -9,7 +9,7 @@ func QSortElementsHT(arr []LinkedList, l, r int) []LinkedList {
return arr
}
func Partition_Hoa(arr []LinkedList, l, r int) int {
func Partition_Hoa(arr []elementHT, l, r int) int {
p := arr[(l+r)/2].name
i := l - 1
j := r + 1

View File

@ -1,7 +1,8 @@
package main
package linked_list
import (
"fmt"
ds "source/pkg/data_struct"
)
/*
@ -21,22 +22,20 @@ def ll_list_all(head) — собирает все записи в список
*/
type LinkedList struct {
name string
phone string
data ds.MyData
next *LinkedList
}
func NewLinkedList(name, phone string) *LinkedList {
func NewLinkedList(data ds.MyData) *LinkedList {
return &LinkedList{
name: name,
phone: phone,
next: nil,
data: data,
next: nil,
}
}
func (ll *LinkedList) ToString() string {
return fmt.Sprintf("Имя: %s, Телефон: %s", ll.name, ll.phone)
return ll.data.ToString()
}
func (ll *LinkedList) Len() int {
@ -55,8 +54,8 @@ func (ll *LinkedList) Len() int {
return len
}
func (ll *LinkedList) Insert(name, phone string) *LinkedList {
newNode := NewLinkedList(name, phone)
func (ll *LinkedList) Insert(data ds.MyData) *LinkedList {
newNode := NewLinkedList(data)
if ll == nil {
return newNode
@ -74,8 +73,8 @@ func (ll *LinkedList) Search(targetName string) (string, bool) {
current := ll
for current != nil {
if current.name == targetName {
return current.phone, true
if current.data.Name == targetName {
return current.data.Phone, true
}
current = current.next
@ -99,7 +98,7 @@ func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) {
if ll == nil {
return nil, false
}
if ll.name == targetName {
if ll.data.Name == targetName {
return ll.next, true
}
@ -107,7 +106,7 @@ func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) {
current := ll.next
for current != nil {
if current.name == targetName {
if current.data.Name == targetName {
prev.next = current.next
}
prev = current
@ -117,17 +116,17 @@ func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) {
return ll, false
}
func (ll *LinkedList) listAll() []LinkedList {
func (ll *LinkedList) listAll() []ds.MyData {
current := ll
listLL := make([]LinkedList, ll.Len())
listLL := make([]ds.MyData, ll.Len())
ind := 0
for current != nil {
listLL[ind] = *current
listLL[ind] = current.data
ind++
current = current.next
}
listLL = QSortElementsHT(listLL, 0, len(listLL)-1)
listLL = ds.QSort(listLL, 0, len(listLL)-1)
return listLL
}

View File

@ -5,6 +5,8 @@ import (
"fmt"
"math/rand"
"os"
bst "source/pkg/bin_search_tree"
ds "source/pkg/data_struct"
)
const (
@ -29,7 +31,7 @@ func isInArr(arr []int, length int, target int) bool {
func main() {
fmt.Println("hello world!")
var head *BinSearchTree = nil
var head *bst.BinSearchTree = nil
arr := make([]int, countNumbers)
@ -48,7 +50,9 @@ func main() {
nameStr := fmt.Sprintf("name_%02d", temp)
phoneStr := fmt.Sprintf("phone_%02d", temp)
head = head.Insert(nameStr, phoneStr)
data := ds.NewData(nameStr, phoneStr)
head = head.Insert(*data)
fmt.Printf("%d ", arr[i])
}
@ -72,7 +76,7 @@ func main() {
head = head.Delete(tarName)
fmt.Printf("\nКоличество узлов после удаления: %d\n", countNodes(head))
fmt.Printf("\nКоличество узлов после удаления: %d\n", head.Len())
fmt.Printf("Поиск '%s' после удаления: ", tarName)
if found, ok := head.Search(tarName); ok {
@ -84,10 +88,3 @@ func main() {
fmt.Println("\ninorder traversal after delete:")
head.BstInorderTraversal()
}
func countNodes(root *BinSearchTree) int {
if root == nil {
return 0
}
return 1 + countNodes(root.left) + countNodes(root.right)
}

View File

@ -0,0 +1,71 @@
package main
import (
"fmt"
// hash_table "hash-table-task/hash-table"
ht "source/pkg/hash_table"
)
/*
1. Сконструировать и реализовать свою хеш таблицу
- изначальный размер 8, коэф-т загрузки 0.75
- Преобразование подаваемого данного в индекс с помощью хеш функции(в ручну) пример: полиномиальный хеш
- Коллизии обрабатываются методом цепочек, каждая корзина таблицы - список в котором хранятся пары значений key-value
- При превышении коэф-та загрузки происходит перехеширование таблицы, размер увеличивается вдвое, все пары заново вставляются в таблицу.
2. Читаем текстовый файл, разбивает на слова, приводим к нижнему регистру, подсчитываем повторения каждого слова: key - слово, value - кол-во повторений
- На вывод 10 самых встречающихся слов, для каждого слова выводим: ind(hash), key, value
- Текст - первая глава, первые три стиха Евгений Онегин
*/
func main() {
// Чтение всего файла
// 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

@ -5,6 +5,9 @@ import (
"fmt"
"math/rand"
"os"
ds "source/pkg/data_struct"
ll "source/pkg/linked_list"
// dg "source/pkg/gendata"
)
const countNumbers = 64
@ -26,7 +29,7 @@ func pressEnterToContinue() {
func main() {
fmt.Println("hello world!")
var head *LinkedList = nil
var head *ll.LinkedList = nil
arr := make([]int, countNumbers)
@ -44,8 +47,9 @@ func main() {
nameStr := fmt.Sprintf("name_%02d", temp)
phoneStr := fmt.Sprintf("phone_%02d", temp)
data := ds.NewData(nameStr, phoneStr)
head = head.Insert(nameStr, phoneStr)
head = head.Insert(*data)
fmt.Printf("%d ", arr[i])
// pressEnterToContinue()
}