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