Vyhledávací stromy: Splay, RB a B+

LAB 12

B4M33PAL - Ing. David Pařil

Splay trees 101

Po každém přístupu "vytáhne" používaný uzel nahoru k rootu.

  • Neudržuje explicitně vyvážení
  • Po operaci provede splay(x): uzel x se přes rotace přesune do rootu
  • Operace běží v \(O(n)\), amortizovaná složitost operací je \(O(\log n)\)

 

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

Existují 3 základní kroky:

Splay operace

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

P

x

1) Zig

\(x\) nemá dědečka

2) Zig-zig

\(x\) a \(p\) jsou na stejné straně vůdči \(G\)

3) Zig-zag

\(x\) a \(p\) jsou na opačné straně vůdči \(G\)

P

G

x

P

G

x

\(x\) nad \(p\)

\(p\) nad \(g\)

\(x\) nad \(p\)

\(x\) nad \(p\)

\(x\) nad \(g\)

Proč při operaci Splay nestačí jen opakovaně používat samotný Zig?

Dvojitý krok není jen rychlejší posun uzlu o dvě úrovně, ale hlavně chytřejší lokální přestavba, která dává splay stromům jejich samooptimalizační chování a amortizované záruky.

Operace na Splay stromu:

Find

  1. Proveď běžné BST hledání
  2. If \(x\) existuje \(\rightarrow\) splay(x)
  3. If \(x\) neexistuje \(\rightarrow\) splay(closest)

Insert

  1. Vlož klíč \(x\) jako v BST
  2. splay(x) do rootu

Delete

  1. find(x)
    if neex. \(\rightarrow\) konec
    if ex. \(\rightarrow\)je root
  2. Smaž root
  3. Máš L a R podstrom

L

R

Operace na Splay stromu:

Delete

  1. find(x)
    if neex. \(\rightarrow\) konec
    if ex. \(\rightarrow\)je root
  2. Smaž root
  3. Máš L a R podstrom

L

R

A) L je prázdný \(\rightarrow\) R je novým rootem

B)Jinak:

  • Najdi maximum v L (nejpravější uzel)
  • splay(maximum v L)
    \(\rightarrow\) stane se rootem L
  • Připoj R jako pravý podstrom tohoto rootu

Splay stromy:

✅ Skvělé, když se přístupy opakují (cache-like chování)

✅ Jednoduchá implementace

✅ Amortizovaně \(O(\log n)\)

Gratulace!

Stali jste se Splay mastery! 😎👍️

Příklad

Let's get splayI'n

Do nejprve prázdného stromu splay tree vkládejte postupně klíče:

 

 

 

Nakreslete strom po každém vložení.

2

7

1

4

3

9

5

6

  Řešení

 Sekvence:

2

7

1

4

3

9

5

6

Příklad

Změna hloubky splay tree

Splay tree obsahuje \(2^n-1\) klíčů s hodnotou \(1, 2, 3, ..., 2^n-1\) a je ideálně vyvážený, to jest má hloubku \(n-1\) .

 

Po vyhledání prvku s klíčem 1 se tento prvek přesune do kořene stromu.

 

Jakou hloubku bude mít výsledný strom? Řešte zvlášť pro sudé a liché \(n\).

8

Strom má \(2^n-1\) klíčů, je perfektní, tedy:

  • hloubka je \(n-1\)
  • klíč 1 je nejmenší \(\rightarrow\) leží v nejlevnějším listu (v hloubce \(n-1\))

Jak probíhá Splay?

  • Opakujeme zig-zig nebo zig v závislosti na počtu uzlů nad námi

Pokud \(n\) je sudé, následuje závěrečný zig

Řešení

1. Zig-zig

Pro \(n=4\):

8

4

12

2

6

10

14

1

3

5

7

9

11

13

15

1. Zig-zig

Pro \(n=4\):

8

2

12

1

4

10

14

3

6

9

11

13

15

5

7

1. Zig-zig

Pro \(n=4\):

8

1

12

2

10

14

4

9

11

13

15

3

6

5

7

1. Zig-zig

2. Zig

Pro \(n=4\):

1

8

2

12

4

10

14

3

6

9

11

13

15

5

7

1. Zig-zig

Pro \(n=5\):

16

8

24

4

12

20

28

2

6

10

14

18

22

26

30

1

3

5

7

9

11

13

15

17

19

21

23

25

27

29

31

1. Zig-zig

Pro \(n=5\):

16

8

24

2

12

20

28

1

4

10

14

18

22

26

30

3

6

9

11

13

15

17

19

21

23

25

27

29

31

5

7

1. Zig-zig

Pro \(n=5\):

16

8

24

1

12

20

28

2

10

14

18

22

26

30

4

9

11

13

15

17

19

21

23

25

27

29

31

3

6

5

7

1. Zig-zig

2. Zig-zig

Pro \(n=5\):

8

1

16

2

12

24

4

10

14

20

28

3

6

9

11

13

15

18

22

26

30

5

7

17

19

21

23

25

27

29

31

1. Zig-zig

2. Zig-zig

Pro \(n=5\):

1

8

2

16

4

12

24

3

6

10

14

20

28

5

7

9

11

13

15

18

22

26

30

17

19

21

23

25

27

29

31

Řešení

Vždy:

  • 1 je v kořeni
  • levý podstrom je prázdný

 

Výsledek:

Během těchto rotací se části stromu posunou v nejhorším případě o 2 úrovně níž, než byly v ideálním stromu.

 

Vyjímky:

\(n=1\): strom má jen \(\{1\}\) \(\rightarrow\) hloubka 0

\(n=2\): \(\{1,2,3\}\) \(\rightarrow\) po splay vznikne řetězec \(1 - 2 - 3\) \(\rightarrow\) hloubka 2

Red-Black Tree

= vyvážené binární stromy, které si hlídají, aby výška byla \(O(\log n)\).

 

Platí následující pravidla:

  1. Každý uzel je B nebo R
  2. Kořen je B
  3. Všechny listy "NIL" jsou B
  4. R uzel nemá R dítě (žádné dvě R za sebou)
  5. Všechny cesty k NIL listům mají stejný počet B uzlů (tzv. black-height)

Operace na RB stromu:

Find

  1. Porovnáme klíč s aktuálním uzlem
    if menší \(\rightarrow\) vlevo
    if větší \(\rightarrow\) vpravo
  2. Najdeš nebo spadneš do NIL

Insert

Delete

Operace na RB stromu:

Insert

  1. Vložíš nový uzel na správné místo
  2. Oprava barev
    • Nový uzel vkládáme R (neporušíš black-height; můžeš porušit pravidlo dvou R za sebou)
    • Řešíme 3 případy:

P

G

U

x

A) Taťka je B

B) Strejda je R

C) Strejda je B

P

G

U

x

P

G

U

x

P

G

U

x

A) Taťka je B

B) Strejda je R

C) Strejda je B (nebo NIL)

P

G

U

x

P

G

U

x

Všechny podmínky OK

Jsme hotovi ✅

Taťku a strejdu dej B

Dědu hoď na R

Opakuj od dědy iterat.

P

G

U

x

If \(x\) je vnitřní dítě, pak malá rotace kolem táty (aby byl vnější)

Pak rotace kolem dědy

Pak přebarvit...

P

G

U

x

P

G

U

x

x

G

U

P

Operace na RB stromu:

Find

Insert

Delete

Operace na RB stromu:

Delete

  1. Smaž: (BST-style)
    • Když má uzel 0 nebo 1 dítě \(\rightarrow\) smaž přímo
    • Když má uzel 2 děti \(\rightarrow\) vyměníš ho s následníkem (dítě)
  2. Oprav barvy:
    • Smažeš R: většinou v pohodě 😏
    • Smažeš B: právě jsi porušil black-height 😫

Viz přednáška (4 různé případy)

Gratulace!

Právě jsi rezignoval na RB stromy! 🤷‍♀️

Příklad

Fun with colors

Navrhněte červenočerné obarvení daných stromů tak, aby vznikl korektní červenočerný strom.

 

Prázdné (NIL) listy nejsou zobrazeny

Navrhněte červenočerné obarvení daných stromů tak, aby vznikl korektní červenočerný strom.

 

Prázdné (NIL) listy nejsou zobrazeny

Příklad 1:

A

E

B

F

C

D

  1. Každý uzel je B nebo R
  2. Kořen je B
  3. Všechny listy "NIL" jsou B
  4. R uzel nemá R dítě (žádné dvě R za sebou)
  5. Všechny cesty k NIL listům mají stejný počet B uzlů

G

Příklad 2:

A

G

B

F

E

D

C

Příklad 3:

D

B

J

H

K

I

F

E

G

A

C

Příklad

One big RB tree

RB-strom má černou výšku rovnou 11.

 

ℹ️ Černá výška je určena jako počet černých uzlů na cestě z kořene do kteréhokoli listu (obsahujícího klíč) zmenšený o 1 (nepočítáme root).

 

Určete, jaký je v tomto stromu maximální možný počet:

  1. B uzlů
  2. R uzlů
  3. všech uzlů

Počet uzlů je maximální pokud je strom ideálně vyvážený a obsahuje R uzly na každé sudé úrovni.

 

Řešení

Celkem tedy: \(N_{max} = 2^0 + 2^1 + ... + 2^{21} = 2^{22} -1\) uzlů

Červené uzly jsou liché úrovně:

\(\textcolor{red}{\textbf{R}_{max}} = 2^1 + 2^3 + ... + 2^{21} = 2 \cdot (1 + 4 + 4^2 + ... + 4^{10}) = 2 \cdot \frac{4^{11}-1}{4-1}\)

Počet R uzlů

Součet prvních \(n\) členů

geometrické posloupnosti

Počet B uzlů

Červené uzly jsou sudé úrovně:

\(\textcolor{bl}{\textbf{B}_{max}} = 2^0 + 2^2 + ... + 2^{20} = (1 + 4 + 4^2 + ... + 4^{10}) = \frac{4^{11}-1}{4-1}\)

A samozřejmě platí \(\textcolor{bl}{\textbf{B}_{max}} + \textcolor{red}{\textbf{R}_{max}} =  N_{max}\)

Příklad

RB-strom manuálně

RB-strom obsahuje 15 klíčů, jeho černá hloubka je 2, tj. obsahuje 10 červených uzlů.

 

Hodnoty klíčů jsou \(1, 2, 3, ..., 7, 8, 21, 22, ..., 26, 27\). Do stromu postupně vložíme další klíče s hodnotou \(11, 12, 13\). Nakreslete původní strom a dále strom po každém vložení.

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

Vkládáme 11

Konflikt

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

Strejda je R

Úloha typu-easy 🤌

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

Taťka a strejda změna na B

Děda změna na R

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

Konflikt

Strejda je R 👏

Přebarvení 🎨

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

Po vložení klíče 11:

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Vkládáme 12

Konflikt

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Rotace na vnějšek

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Rotace výš

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Přebarvení

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Po vložení klíče 12:

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

13

Vkládáme 13

Konflikt

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Strejda R \(\rightarrow\) barvíme 👌

13

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Strejda R \(\rightarrow\) barvíme 👌

Konflikt

13

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

Strejda B \(\rightarrow\) rotujeme 😟

13

Řešení

8

4

2

1

3

6

5

7

21

22

23

24

25

26

27

11

12

13

Po vložení klíče 13:

Hotovo ✅

Příklad

The impossible RB-tree

Rozhodněte, zda existuje příklad regulárního (každý vnitřní uzel má dva potomky) binárního stromu který nelze obarvit podle pravidel RB-stromu.

 

Příklad buď uveďte nebo zdůvodněte jeho nemožnost.

Řešení

Ano, takový regulární strom existuje.

Může mít 2 nebo 3 B uzly

Nedokáže mít méně než 4 B uzly

B+ stromy

B+ strom je vyvážený vyhledávací strom používaný hlavně v databázích.

 

  • Každý uzel (kromě kořene) má "hodně" potomků / klíčů \(\rightarrow\) malá výška
  • Všechny hodnoty jsou uloženy v listech 🌿
  • Vnitřní uzly obsahují pouze klíče 🔑 pro navigaci...
  • Listy jsou propojené do Linked-listu
  • Strom je vždy vyvážený ⚖️

Struktura uzlu

10

20

30

40

Uzel...

...řádu 5:

... se 4mi klíči ...

Struktura uzlu

10

20

30

40

1

2

3

4

20

23

26

29

20 ≤

< 30

Data

Data

Data

Data

List...

List 🌿 

Node 

Struktura uzlu

List 🌿 

Node 

List 🌿 

List 🌿 

List 🌿 

List 🌿 

List 🌿 

List 🌿 

List 🌿 

List 🌿 

Operace na B+ stromu:

Find

  1. Proveď běžné BST hledání

Insert

  1. Najdeme, kam \(x\) patří
  2. Vložíme mezi ostatní klíče
  3. If list přeteče:
    1. Rozdělíme list na 2
    2. Do rodičovského uzlu vložíme první klíč R listu
    3. Propojíme listy

Delete

  1. Smaž \(x\)
  2. if list nemá min. počet prvků:
    1. Snažíme si půjčit od sourozence
    2. Pokud selžeme, provedem merge s využitím klíče z rodiče

 

Gratulace!

Vždyť už jsme to vlastně uměli... 😏

Příklad

B+ strom na Čas

Vybudujte B+ strom řádu 3 tak, že do prázdného stromu vložíte v uvedeném pořadí klíče:

32

18

31

59

20

23

24

36

60

58

15

57

51

17

16

26

42

21

43

12

Nakreslete strom po každé operaci Insert.

Na řešení máte 7 minut.

Snažte se získat co nejvíce bodů.

32

18

31

59

20

23

24

36

60

58

15

57

51

17

16

26

42

21

43

12

Vybudujte B+ strom řádu 1 tak, že do prázdného stromu vložíte v uvedeném pořadí klíče:

Nakreslete strom po každé operaci Insert.

Na řešení máte 7 minut.

Snažte se získat co nejvíce bodů.

  Řešení

 Sekvence:

32

18

31

59

20

23

24

36

60

58

15

57

51

17

16

26

42

21

43

12

řád 3

Na
Viděnou
Za týden :)