From b3688d3ed9107eb9a2178e492e81fe5fa6b5a5fa Mon Sep 17 00:00:00 2001 From: GordStep Date: Wed, 13 May 2026 21:25:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=83=20=D1=81=D0=BE=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D0=B0=D0=BC=D0=B8,?= =?UTF-8?q?=20=D1=87=D1=82=D0=BE=D0=B1=D1=8B=20=D0=BE=D0=BD=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=85=D0=BE=D0=B4=D0=B8=D0=BB=D0=B8=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bin_search_tree/bin_search_tree.go | 191 +++++++++++------- .../pkg/structures/hash_table/hash_table.go | 20 +- .../pkg/structures/linked_list/linked_list.go | 71 ++++--- .../source/tests/benchmark/main.go | 11 +- 4 files changed, 177 insertions(+), 116 deletions(-) diff --git a/stepushovgs/data-structures/source/pkg/structures/bin_search_tree/bin_search_tree.go b/stepushovgs/data-structures/source/pkg/structures/bin_search_tree/bin_search_tree.go index b3a653a..f647ddb 100644 --- a/stepushovgs/data-structures/source/pkg/structures/bin_search_tree/bin_search_tree.go +++ b/stepushovgs/data-structures/source/pkg/structures/bin_search_tree/bin_search_tree.go @@ -6,14 +6,18 @@ import ( ) type BinSearchTree struct { - data ds.MyData - - left *BinSearchTree - right *BinSearchTree + root *BSTree } -func NewBinSearchTree(data ds.MyData) *BinSearchTree { - return &BinSearchTree{ +type BSTree struct { + data ds.MyData + + left *BSTree + right *BSTree +} + +func NewBinSearchTree(data ds.MyData) *BSTree { + return &BSTree{ data: data, left: nil, right: nil, @@ -21,30 +25,42 @@ func NewBinSearchTree(data ds.MyData) *BinSearchTree { } 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() *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 (bst *BinSearchTree) Minimum() *BSTree { + return bst.root.Minimum() } -func (node *BinSearchTree) PrintNode() { +func (root *BSTree) Minimum() *BSTree { + 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.right == nil { + return root + } + return root.right.Maximum() +} + +func (node *BSTree) PrintNode() { fmt.Print(node.data.ToString()) } -func (node *BinSearchTree) ToString() string { +func (node *BSTree) ToString() string { if node == nil { return "nil" } @@ -52,28 +68,37 @@ func (node *BinSearchTree) ToString() string { } func (bst *BinSearchTree) BstInorderTraversal() { - if bst != nil { - bst.left.BstInorderTraversal() - bst.PrintNode() + bst.root.BstInorderTraversal() +} + +func (root *BSTree) BstInorderTraversal() { + if root != nil { + root.left.BstInorderTraversal() + root.PrintNode() fmt.Println() - bst.right.BstInorderTraversal() + root.right.BstInorderTraversal() } } func (bst *BinSearchTree) BstPreorderTraversal() { - if bst != nil { - bst.PrintNode() - bst.left.BstPreorderTraversal() - bst.right.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.search(targetName) + node, ok := bst.root.search(targetName) if ok { - return node.ToString(), true + return node.data.Phone, true } return "", false } @@ -88,7 +113,7 @@ func (bst *BinSearchTree) Search(targetName string) (string, bool) { return search(x.right, k) */ // Приватная вспомогательная функция поиска -func (node *BinSearchTree) search(targetName string) (*BinSearchTree, bool) { +func (node *BSTree) search(targetName string) (*BSTree, bool) { if node == nil { return nil, false } @@ -101,32 +126,38 @@ func (node *BinSearchTree) search(targetName string) (*BinSearchTree, bool) { 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 // } -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 // Заменяем существующее значение +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, + } } - return node + + 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 } // Delete удаляет узел по имени. @@ -153,45 +184,59 @@ Node delete(root : Node, z : T): // корень поддерев return root */ -func (root *BinSearchTree) Delete(targetName string) *BinSearchTree { +func (bst *BinSearchTree) Delete(targetName string) bool { + if bst.root == nil { + 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) + 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) + root.right = root.right.delete(targetName) } else { - if root.left != nil { - return root.left - } else if root.right != nil { + // Нашли узел для удаления + + // Случай 1: нет левого потомка + if root.left == nil { return root.right - } else { - return nil } + + // Случай 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(depth int) { +func (bst *BinSearchTree) PrintAll() { + bst.root.printAll(0) +} + +func (bst *BSTree) printAll(depth int) { if bst == nil { return } - bst.right.PrintAll(depth + 1) + bst.right.printAll(depth + 1) for i := 0; i < depth; i++ { fmt.Printf("\t") } bst.PrintNode() - bst.left.PrintAll(depth + 1) + bst.left.printAll(depth + 1) } diff --git a/stepushovgs/data-structures/source/pkg/structures/hash_table/hash_table.go b/stepushovgs/data-structures/source/pkg/structures/hash_table/hash_table.go index b4ef466..fa566b2 100644 --- a/stepushovgs/data-structures/source/pkg/structures/hash_table/hash_table.go +++ b/stepushovgs/data-structures/source/pkg/structures/hash_table/hash_table.go @@ -1,9 +1,7 @@ package hash_table import ( - "bufio" "fmt" - "os" ds "source/pkg/data_struct" ) @@ -54,6 +52,10 @@ func (ht *HashTable) GetIndex(name string) int { return hash % ht.capacity } +func (ht *HashTable) Len() int { + return ht.size +} + // func (ht *HashTable) getIndex(hash int) int { // return hash % ht.capacity // } @@ -88,7 +90,7 @@ func (h *HashTable) Insert(new ds.MyData) { h.size++ } -func (h *HashTable) Get(name string) (phone string, status bool) { +func (h *HashTable) Search(name string) (phone string, status bool) { ind := h.GetIndex(name) buck := h.buckets[ind] @@ -106,10 +108,10 @@ func (h *HashTable) Get(name string) (phone string, status bool) { return "", false } -func pressEnterToContinue() { - fmt.Print("Нажмите Enter для продолжения...") - bufio.NewReader(os.Stdin).ReadBytes('\n') -} +// func pressEnterToContinue() { +// fmt.Print("Нажмите Enter для продолжения...") +// bufio.NewReader(os.Stdin).ReadBytes('\n') +// } // resize - увеличивает размер таблицы func (ht *HashTable) resize() { @@ -135,7 +137,7 @@ func (ht *HashTable) resize() { ht.capacity = newCapacity } -func (ht *HashTable) Remove(name string) bool { +func (ht *HashTable) Delete(name string) bool { ind := ht.GetIndex(name) buck := ht.buckets[ind] @@ -167,7 +169,7 @@ func (ht *HashTable) Remove(name string) bool { } func (ht *HashTable) Contains(name string) bool { - _, ok := ht.Get(name) + _, ok := ht.Search(name) return ok } diff --git a/stepushovgs/data-structures/source/pkg/structures/linked_list/linked_list.go b/stepushovgs/data-structures/source/pkg/structures/linked_list/linked_list.go index eb1467c..82317b8 100644 --- a/stepushovgs/data-structures/source/pkg/structures/linked_list/linked_list.go +++ b/stepushovgs/data-structures/source/pkg/structures/linked_list/linked_list.go @@ -22,19 +22,26 @@ def ll_list_all(head) — собирает все записи в список */ type LinkedList struct { - data ds.MyData - - next *LinkedList + head *LList } -func NewLinkedList(data ds.MyData) *LinkedList { - return &LinkedList{ +type LList struct { + data ds.MyData + + next *LList +} + +func NewLinkedList(data ds.MyData) *LList { + return &LList{ data: data, next: nil, } } -func (ll *LinkedList) ToString() string { +func (ll *LList) ToString() string { + if ll == nil { + return "nil" + } return ll.data.ToString() } @@ -45,7 +52,7 @@ func (ll *LinkedList) Len() int { } len := 0 - current := ll + current := ll.head for current != nil { len++ current = current.next @@ -54,23 +61,23 @@ func (ll *LinkedList) Len() int { return len } -func (ll *LinkedList) Insert(data ds.MyData) *LinkedList { +func (ll *LinkedList) Insert(data ds.MyData) { newNode := NewLinkedList(data) - if ll == nil { - return newNode + if ll.head == nil { + ll.head = newNode + return } - current := ll + current := ll.head for current.next != nil { current = current.next } current.next = newNode - return ll } func (ll *LinkedList) Search(targetName string) (string, bool) { - current := ll + current := ll.head for current != nil { if current.data.Name == targetName { @@ -83,7 +90,7 @@ func (ll *LinkedList) Search(targetName string) (string, bool) { } func (ll *LinkedList) PrintAll() { - current := ll + current := ll.head index := 0 for current != nil { @@ -93,33 +100,33 @@ func (ll *LinkedList) PrintAll() { } } -func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) { - - if ll == nil { - return nil, false - } - if ll.data.Name == targetName { - ll.data = ll.next.data - ll.next = ll.next.next - return ll, true +func (ll *LinkedList) Delete(targetName string) bool { + if ll.head == nil { + return false } - prev := ll - current := ll.next + // Особый случай: удаление головы списка + if ll.head.data.Name == targetName { + // Сдвигаем данные и указатель + *ll.head = *ll.head.next + return true + } - for current != nil { - if current.data.Name == targetName { - prev.next = current.next + // Стандартное удаление из середины/конца + current := ll.head + for current.next != nil { + if current.next.data.Name == targetName { + current.next = current.next.next + return true } - prev = current current = current.next } - return ll, false + return false } func (ll *LinkedList) listAll() []ds.MyData { - current := ll + current := ll.head listLL := make([]ds.MyData, ll.Len()) ind := 0 @@ -139,7 +146,7 @@ func (ll *LinkedList) GetByInd(ind int) (ds.MyData, bool) { } index := 0 - current := ll + current := ll.head for current != nil { if index == ind { return current.data, true diff --git a/stepushovgs/data-structures/source/tests/benchmark/main.go b/stepushovgs/data-structures/source/tests/benchmark/main.go index cd0e575..0140589 100644 --- a/stepushovgs/data-structures/source/tests/benchmark/main.go +++ b/stepushovgs/data-structures/source/tests/benchmark/main.go @@ -6,6 +6,8 @@ import ( 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" @@ -31,9 +33,9 @@ type TestData struct { type DataStructure interface { Insert(data ds.MyData) - Search(name string) *ds.MyData + Search(name string) (string, bool) Delete(name string) bool - Size() int + Len() int } func uniqueElements(data []ds.MyData) []ds.MyData { @@ -89,6 +91,7 @@ func GenerateTestData() TestData { } } +// Тест вставки массива данных (один раз) func testOneInsert(structure DataStructure, data []ds.MyData) float64 { start := time.Now() @@ -147,6 +150,10 @@ func main() { testData := GenerateTestData() var head_ll *ll.LinkedList = nil + var head_ht *ht.HashTable = nil + var head_bst *bst.BinSearchTree = nil Test("Связный список", head_ll, testData) + Test("Связный список", head_ht, testData) + Test("Связный список", head_bst, testData) }