avl.go — karkasas
Sukurk avl.go. Karkasas kaip įprasta; kūnai tavo.
Didesnė šio failo dalis yra vienuoliktos pamokos kodas, perkeltas be pakeitimų
— Get, Keys, Range, Min, Max yra tie patys, tik *node pakeistas į
*avlNode. Rotacijos keičia formą, ne reikšmę. Kopijuok juos ir nesijausk
sukčiaudamas: tai ir yra pastebėjimas, kad AVL medis yra BST.
Tikrai naujo — penkios funkcijos: height, balance, fix, dvi rotacijos ir
rebalance.
Ką verta pasižymėti:
heightprivalo būti sauginilatžvilgiu. Nesamo pomedžio aukštis yra 0. Pusė visų AVL klaidų yra pamirštanilpatikra būtent čia, ir jos pasirodo kaip „kartais nesubalansuota", ne kaip griūtis.fixpo rotacijos kviečiamas dviem mazgams, ir tvarka svarbi. Pirma tam, kuris nusileido, paskui tam, kuris pakilo — antrojo aukštis priklauso nuo pirmojo.- Vienodas raktas nebalansuojamas.
Putsu esamu raktu tik pakeičia įrašą; medžio forma nepasikeitė, tad ir taisyti nėra ko. - Rotacijos nėra palyginimai.
c.Hit()kviečiamas tik lyginant raktus. Jei suskaičiuosi ir rotacijas, šeštas žingsnis nustos veikti — o jis kaip tik apie tai, ko skaitiklis nemato. Height()čia yraO(1)— grąžinaroot.h. Vienuoliktoje pamokoje tam reikėjo apeiti visą medį. Tai nemokamas priedas prie lauko, kurį jau pridėjai.
Įterpimas turi būti rekursinis. Vienuoliktos pamokos ciklas su &(*cur).left
čia netinka: taisyti reikia grįžtant atgal, o ciklas kelio atgal neturi.
rebalance grąžina naują pomedžio šaknį, ir kviečiantysis privalo tą
reikšmę pasiimti:
n.left = insert(n.left) // teisingai — pomedis gali turėti naują šaknį
insert(n.left) // klaida — rotacija įvyko ir buvo pamesta
Antrasis variantas kompiliuojasi ir jokios klaidos neparodo. Len() didėja
kiekvienu kvietimu, nes skaitiklis didinamas ten, kur sukuriamas lapas — bet
pats lapas išmetamas, tad Get rakto neberanda. Pamatuota: krenta pats pirmas
testas — Get("00000"): ok=false.
Tylus nieko nedarymas, kuris dar ir didina skaitiklį, yra piktesnis gedimas nei
griūtis. Todėl avl_test.go pirmiausia ir tikrina, ar kiekvienas įdėtas raktas
randamas.