2026-rff_mp/stepushovgs/data-structures/source/pkg/hash_table/hash_table.go

243 lines
4.4 KiB
Go
Raw Normal View History

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