2026-rff_mp/stepushovgs/data-structures/source/pkg/hash_table/hash_table.go
GordStep 1b21f97e28 Изменение иерархии проекта
- test/ -- папка с файлами для тестов каждой структуры
- pkg/ -- папка с реализациями и вспомогательными модулями
2026-05-09 22:34:03 +03:00

243 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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