Temat: Struktury do przechowywania danych w pami ci zewn trznej. B - drzewa. B* - drzewa. B+ - drzewa. Podstawow jednostk w operacjach wej cia - wyj cia zwi zanych z dyskiem (pami ci zewn trzn ) jest blok. czas dost pu || czas szukania cie ki + bezwładno obrotowa (ok. 1/2 obrotu) + czas przesyłania 1 Przykład Załó my, e dysk ma nast puj ce parametry: • 40 ms trwa znalezienie cie ki, • wykonuje 3000 obrotów na minut , • przesyła dane do pami ci wewn trznej z pr dko ci 1000 kB/s. 1. Odczytujemy blok 5kB z dysku i przesyłamy do pami ci wewn trznej: czas dost pu = 40 ms + 10 ms +5 ms = 55 ms 2. Odczytujemy dwa bloki po 5 kB z dysku i przesyłamy do pami ci wewn trznej: czas dost pu = 2 ⋅ ( 40 ms + 10 ms + 5 ms) = 110 ms 3. Odczytujemy blok 10 kB z dysku i przesyłamy do pami ci wewn trznej: czas dost pu = 40 ms + 10 ms +10 ms = 60 ms Ka dy dost p do dysku jest bardzo kosztowny. Dane w pami ci zewn trznej powinny by uj te w tak struktur , która minimalizuje liczb dost pów. 2 Przyjmijmy, e w pliku znajduje si n danych. Rozmiar bloku danych, który przesyłamy do pami ci wewn trznej wynosi k. Rozwa amy algorytmy realizacji operacji słownikowych: • search(d, S) - wyszukiwanie danych d w zbiorze S • insert(d, S) - dodanie danych d do zbioru S • delete(d, S) - usuwanie danych d ze zbioru S. 1. Pliki nieuporz dkowane Jeden dost p do pliku realizuje zapis albo odczyt bloku zawieraj cego k danych. • search(d, S) : Algorytm wyszukiwania polega na przesłaniu co najwy ej n/k bloków. • insert(d, S) : Algorytm wstawianiu wymaga przesłania co najwy ej n/k bloków w celu sprawdzenia, czy element d ∈S. Je eli ostatni blok jest pełny i d∉S, to element d jest wstawiany do nowego, n/k +1 bloku i nowy blok jest przesłany (zapisywany) w pliku. Tak wi c koszt pesymistyczny całej operacji wynosi n/k +1. 3 • delete(d, S) : Algorytm usuwania wymaga przesłania co najwy ej n/k bloków w celu sprawdzenia, czy element d ∈S. Je eli element d znajdował si w bloku o numerze i, to blok ten jest uzupełniany ostatnim elementem z bloku o numerze n/k , a nast pnie zostaje zapisany jako blok o numerze i. Zmieniony ostatni blok pliku jest równie zapisywany na dysku, o ile po usuni ciu z niego elementu ni stał si pusty. Koszt całkowity operacji delete wynosi wi c: i+1+2. Je eli i = n/k -1, to koszt wynosi: n/k -1+1+2= n/k +2 i jest to koszt pesymistyczny operacji delete. l l d 1 2 3 ............ i .......... n/k -1 n/k Podstawow wad tej struktury jest: - długi czas działania operacji, - zestaw danych jest nieuporz dkowany. Podstawow zalet natomiast jest to, e: - nie jest u ywana dodatkowa pami , - prostota algorytmów. 4 Struktura plików nieuporz dkowanych mo e by zastosowana, gdy dane s zawsze przetwarzane sekwencyjnie, bez wykorzystania porz dku. 2. Struktury danych realizuj ce wył cznie wyszukiwanie w pliku danych a) Pliki z funkcj mieszaj c Załó my, e mamy okre lon funkcj mieszaj c : h : U → {0,1,... n / k − 1}, gdzie U jest uniwersum słownika Warto ci funkcji haszuj cej jest numer bloku, w którym powinien znajdowa si wyszukiwany element. Tablica haszuj ca zawiera adresy bloków. Tablica ta jest równie zapisana na dysku. Algorytm wyszukiwania polega na przesłaniu do pami ci wewn trznej bloku o numerze h(d). Koszt operacji jest zatem stały. Zalet tej metody jest bardzo szybki czas realizacji operacji search. Wad jest zu ycie dodatkowej pami ci dyskowej na tablic haszuj c . Struktura taka nie powinna by u ywana, gdy słownik jest modyfikowany, czyli realizowane jest usuwanie b d wstawianie. 5 b) Sekwencyjne pliki indeksowe W tej metodzie dane przechowywane s w tzw. pliku głównym, uporz dkowanym wg danej relacji. Oprócz pliku głównego tworzony jest plik pomocniczy nazywany indeksem rzadkim. Dla ka dego bloku pliku głównego w indeksie rzadkim znajduje si para (v, b), gdzie b jest adresem (numerem) bloku, a v najmniejsz dan w bloku według relacji porz dkuj cej. Plik główny i indeks rzadki (1, 1) (9, 2) (17, 3) (51, 4) 1: 1 2 5 8 2: 9 10 13 15 .... 3: 17 18 45 49 4: 51 53 80 91 Zauwa my, e plik główny ma n/k bloków, a indeks rzadki n/k2 bloków. Algorytm wyszukiwania search(d, S) realizuje albo: • sekwencyjne przegl danie bloków indeksu rzadkiego, a do momentu: (*) znalezienia bloku (v, b) w pliku indeksu rzadkiego takiego, e v>d. Do pami ci wewn trznej przesyłany jest blok b-1. Je eli dla wszystkich par indeksu rzadkiego warunek v>d nie jest spełniony, to przesyłamy ostatni blok pliku głównego. Koszt pesymistyczny operacji wyszukiwania wynosi 1+ n/k2 6 albo • binarne wyszukiwanie bloku spełniaj cego warunek (*). Koszt pesymistyczny wówczas 2+log2 n/k2 . operacji wyszukiwania wynosi Zalet tej struktury jest niski czas wyszukiwania (zwłaszcza przy zastosowaniu wyszukiwania binarnego) i fakt, e dane w pliku s uporz dkowane. Wad natomiast jest konieczno utworzenia dodatkowego pliku indeksu rzadkiego i fakt, e nie opłaca si w tej strukturze, ze wzgl du na wysoki koszt czasowy, realizacja pozostałych operacji słownikowych. 3. Definicja B - drzewa ( B - drzewo klasyczne) B - drzewo T jest drzewem wielokierunkowym z korzeniem o nast puj cych własno ciach: 1. Ka dy w zeł x ma nast puj ce pola: (a) n[x] - liczba kluczy aktualnie zapami tanych w w le x, (b) n[x] kluczy zapami tanych w porz dku niemalej cym key1 [x]≤ key2 [x] ≤...≤ keyn[x] [x] (keyi [x]- i - ty klucz w w le x) (c) leaf[x] - pole logiczne, którego warto ci jest 1, je li x jest li ciem albo 0, je li x jest w złem wewn trznym. Typ wska nika na w zeł B - drzewa oznaczmy przez wsk. 7 2. Je li x jest w złem wewn trznym, to zawiera tak e n[x]+1 wska ników do synów c1 [x], c2 [x], cn[x]+1 [x]. Li cie nie maj synów, wi c ich pola ci nie s zdefiniowane. Schemat budowy w zła wewn trznego x typu wsk n[x] key1 [x] key2 [x] ...... keyn[x] [x] leaf[x] c1 [x] c2 [x] ...... cn[x][x] cn[x]+1 [x] 3. Klucze keyi [x] rozdzielaj przedziały kluczy pami tanych w poddrzewach: Je li ki jest dowolnym kluczem z poddrzewa o korzeniu ci[x], to k1 ≤ key1 [x ] ≤ k 2 ≤ key 2 [x ] ≤ ... ≤ key n [ x ] [x ] ≤ k n [ x ]+1 4. Wszystkie li cie le na tej samej gł boko ci. 5. Istniej dolne i górne ograniczenia na liczb kluczy w danym w le. Ograniczenia te zale od ustalonej liczby całkowitej t ≥ 2 nazywanej minimalnym stopniem B-drzewa. (a) Ka dy w zeł ró ny od korzenia musi mie co najmniej t-1 kluczy. Ka dy w zeł wewn trzny ró ny od korzenia ma zatem co najmniej t synów. Je li drzewo jest niepuste, to korze musi mie co najmniej jeden klucz. (b) Ka dy w zeł mo e zawiera co najwy ej 2t-1 kluczy. Dlatego ka dy w zeł wewn trzny mo e mie co 8 najwy ej 2t synów. Powiemy, e w zeł jest pełny, je li zawiera dokładnie 2t-1 kluczy. Najprostsze B-drzewo ma minimalny stopie t = 2. Ka dy w zeł wewn trzny ma wtedy 1, 2 lub 3 synów. W praktyce u ywa si du o wi kszych warto ci t (co najmniej 100). Przykład B-drzewo o minimalnym stopniu t = 3. Ka dy w zeł wewn trzny ró ny od korzenia ma co najmniej t-1=2 kluczy i co najwy ej 2t-1=5 kluczy. Ka dy w zeł wewn trzny ma 6 wska ników. 1 30 2 10 20 3 1 3 4 0 2 40 60 0 1 4 12 13 14 18 4. Maksymalna wysoko 1 4 22 24 26 28 0 1 ... ... ... B- drzewa Mo na si spodziewa , e koszt operacji słownikowych zrealizowanych na B-drzewie zasadniczo zale y od jego wysoko ci. Przez n oznaczymy rozmiar słownika. Jaka b dzie maksymalna wysoko B-drzewa dla danego n≥1 i minimalnego stopnia t≥2? 9 Je eli B - drzewo ma wysoko h, to liczba jego w złów jest najmniejsza, gdy korze zawiera jeden klucz, a wszystkie pozostałe w zły zawieraj t-1 kluczy. 1 ... t-1 ... t-1 ... t-1 t-1 t-1 t-1 ... t-1 t-1 t-1 t-1 Gł boko n ≥ 1 + (t − 1) St d: h ≤ log t 2t i =1 ... t-1 t-1 t-1 ... t-1 Liczba w złów 0 1 2 3 4 h ... 1 2 2t 2t2 i −1 t h −1 = 1 + 2(t − 1) = 2t h − 1 t −1 n +1 2 4. Wyszukiwanie w B-drzewie x - wska nik na B-drzewo, k - poszukiwany klucz Je eli k znajduje si w drzewie, to warto ci funkcji B_tree_search jest wska nik na w zeł, w którym znajduje si poszukiwany klucz. Je eli k nie ma w drzewie, to funkcja zwraca adres pusty. 10 B_tree_search(x, k) i=1; while (i<=n[x] && k>keyi [x]) i++; if (i<= n[x] && (k == keyi [x]) return x; if (leaf[x]) return NULL; else { Disk_Read(ci [x]); return B_tree_search(ci [x],k); } Zło ono czasowa Liczba dost pów do stron na dysku w funkcji B_tree_search wynosi Θ(h ) = Θ(log t n ) , gdzie h jest wysoko ci drzewa, a n liczb zapisanych w nim kluczy. 6. Tworzenie pustego B-drzewa Wstawienie pierwszego klucza do B - drzewa jest poprzedzone utworzeniem pustego w zła, który b dzie korzeniem drzewa (adres root). B_tree_Create (root) “przydziel pam dla root”; leaf[root]=1; n[root]=0; Disk_Write(root); 11 Koszt czasowy operacji tworzenia pustego B-drzewa jest O(1) ze wzgl du na liczb dost pów dyskowych. 7. Rozbijanie w zła w B-drzewie Kluczowym elementem algorytmu wstawiania do B - drzewa jest rozbijanie "pełnego" w zła y na dwa w zły o t-1 kluczach. W zeł y jest rozbijany wzgl dem rodkowego klucza keyt [y], który jest przesuwany do ojca w zła y. Załó my tymczasowo, e ojciec w zła y nie jest "pełny". Je eli w zeł y jest korzeniem drzewa (nie ma ojca), to wysoko drzewa po rozbiciu ro nie o 1. x - "niepełny" w zeł wewn trzny, znajduj cy si w pami ci wewn trznej, i - indeks z zakresu 1..n[x]+1, y - "pełny" w zeł taki, e y = ci [x]. Procedura B_tree_Split_Child rozbija y na dwa w zły i zmienia x tak, aby był uwzgl dniony jego nowy syn. B_tree_Split_Child(x, i, y) „przydziel adres nowemu w złowi z”; leaf[z]=leaf[y]; n[z]=t-1; for (j=1; j<=t-1; j++) keyj [z]= keyj+t [y]; if (!leaf[y]) for (j=1; j<=t; j++) cj [z]= cj+t [y]; n[y]=t-1; for (j=n[x]+1;j>=i+1;j--) cj+1 [x]= cj[x]; ci+1 [x]= z; for (j=n[x]; j>=i; j--) do keyj+1 [x]= keyj[x]; keyi [x]= keyt[y]; n[x]=n[x]+1; Disk_Write(y); Disk_Write(z); Disk_Write(x); 12 Przykład x keyi-1[x] keyi[x] ... keyi+1[x] keyi[x] keyi-1[x] x N, W ... ... N, S, W ... y=ci [x] y=ci [x] z=ci+1 [x] P Q R P Q R S T U V T U V Rozbijanie w zła z t = 4. W zeł y jest rozbijany na dwa w zły: y oraz z, rodkowy klucz S z y zostaje przesuni ty do ojca y. root H r ADFH L N P r A D F s L N P Rozbijanie korzenia z t = 4. Korze r jest rozbijany na dwa w zły i jest tworzony nowy korze s. Nowy korze zawiera rodkowy klucz z r, a oba w zły powstałe z rozbicia zostaj jego synami. Rozbicie korzenia powoduje zwi kszenie wysoko ci drzewa o 1. 13 Koszt czasowy realizacji procedury B_tree_Split_Child jest równie O(1). 8. Wstawianie klucza do B – drzewa root – korze drzewa, k- wstawiany element B_tree_Insert(root , k) r=root; if (n[r]==2t-1) { “przydziel pami w złowi s”; root=s; leaf[s]=0; n[s]=0; c1[s]=r; B_tree_Split_Child(s, 1, r); B_tree_Insert_NoFull(s, k); } else B_tree_Insert_NoFull(r, k); B_tree_Insert_NoFull(x, k); i=n[x]; if (leaf[x]) { while (i>=1 && k<keyi [x]) do { keyi+1 [x]= keyi [x]; i=i--; } keyi+1 [x]=k; n[x]=n[x]+1; Disk_Write(x); } else { while (i>=1 && (k<keyi [x]) i--; i++; 14 } Disk_Read(ci [x]); if (n[ci [x]]=2t-1) { B_tree_Split_Child(x, i, ci [x]); if (k> keyi [x]) i++; } B_tree_Insert_NoFull(ci [x], k); Przykład (t = 3) a) pocz tkowe drzewo G M P X ACDE JK N0 RSTUV YZ b) po wstawieniu B G M P X A BC D E JK N0 RSTUV YZ c) po wstawieniu Q G M P T X A BC D E JK N0 QRS UV YZ d) po wstawieniu L P G M A BC D E JK L T X N 0 Q R S U V Y Z 15 e) po wstawieniu F P C G M A B DEF JK L T X N 0 Q R S U V Y Z Koszt pesymistyczny operacji wstawiania do B - drzewa jest rz du wysoko ci drzewa O(h)=O(logt n). Jak cz sto mo na si spodziewa konieczno ci rozdzielania w złów? Rozdzielanie korzenia B-drzewa powoduje powstanie dwóch nowych w złów. We wszystkich pozostałych przypadkach rozdzielanie zwi ksza liczb w złów w B - drzewie tylko o 1. Podczas konstruowania B - drzewa o p - w złach rozdzielenie w zła trzeba wykona p - h razy, gdzie h jest wysoko ci B drzewa. W B - drzewie o p w złach i minimalnym stopniu t jest co najmniej 1 + (t − 1)( p − 1) kluczy. Proporcja liczby rozdziele do liczby kluczy w B - drzewie dana jest zatem wzorem: p−h 1 + (t − 1)( p − 1) Po podzieleniu licznika i mianownika przez p-h i obserwacji, e 1 d p−h y do 0, a p −1 p−h d y do 1 ze wzrostem p, wnioskujemy, e rednie prawdopodobie stwo rozdzielania 1 wynosi: t − 1 . Na przykład, gdy t = 5 prawdopodobie stwo to jest równe 0,25, ale dla t=500 wynosi tylko 0,002. Jest to zgodnie z oczekiwaniem; im wi ksza pojemno jednego w zła, tym rzadziej trzeba w zły rozdziela . 16 9. Usuwanie klucza z B – drzewa Załó my, e chcemy usun klucz k z poddrzewa o korzeniu w w le x. Zakładamy równie , e gdy z korzenia x zostaj usuni te wszystkie klucze i x jest w złem wewn trznym, to jest on wtedy usuwany, a jego jedyny syn ci[x] zostaje nowym korzeniem drzewa. W ten sposób wysoko drzewa jest zmniejszana o jeden, a własno , e korze drzewa zawiera co najmniej jeden klucz, jest zachowana (chyba, e drzewo jest puste). Opis algorytmu usuwania klucza z B - drzewa 1. Je li klucz k jest w w le x i x jest li ciem, to usu klucz k z x. 2. Je li klucz k jest w w le x i x jest w złem wewn trznym, to wykonaj: a) Niech y b dzie synem x poprzedzaj cym k. Je li y ma co najmniej t kluczy, to w poddrzewie o korzeniu y wyznacz poprzednik k' klucza k. Rekurencyjnie usu k' i w w le x zast p k przez k'. b) Symetrycznie, je li syn z, który wyst puje po k w w le x, ma co najmniej t kluczy, to wyznacz nast pnik k' dla k w poddrzewie o korzeniu w z. Rekurencyjnie usu k' i zast p k przez k' w x. c) Je li obaj synowie y i z maj tylko po t-1 kluczy, to przenie k i wszystko z w zła z do y. W wyniku tej operacji klucz k i wska nik do z zostaj usuni te z x. Nast pnie zwolnij pami przydzielon dla z i usu rekurencyjnie k z y. 3. Je eli klucz k nie wyst puje w wewn trznym w le x, to wyznacz korze ci[x] poddrzewa, w którym musi znajdowa si k (je li tylko jest w drzewie). Je li ci[x] ma tylko t-1 kluczy, to wykonaj krok 3a) lub 3b) w celu zagwarantowania, e zej cie rekurencyjne nast puje do 17 w zła zawieraj cego co najmniej t kluczy. Nast pnie usu rekurencyjnie k z wła ciwego poddrzewa. a) Je li w w le ci[x] jest tylko t-1 kluczy, ale jeden z jego s siednich braci ma t kluczy, to umie w ci[x] dodatkowy klucz, przesuwaj c odpowiedni klucz z x, a w jego miejsce przenosz c klucz z lewego lub prawego brata - z tego, który zawiera t kluczy. Na koniec przesu jeszcze z wybranego brata do ci[x] wska nik do odpowiedniego syna. b) Je li ci[x] i s siedni bracia maj po t-1 kluczy, to poł cz ci[x] z jednym z s siednich braci, przesuwaj c odpowiedni klucz z x do nowo powstałego w zła. Przesuni ty klucz jest kluczem rodkowym w nowym w le. Poniewa wi kszo kluczy w B - drzewie znajduje si w li ciach, mo emy oczekiwa , e wła nie te klucze s usuwane najcz ciej. W tym przypadku usuwanie jest wykonywane w jednym przej ciu od korzenia do li cia. Je li jest usuwany klucz z w zła wewn trznego, to oprócz przej cia "w dół" drzewa mo e by jeszcze konieczny powrót do w zła, którego klucz jest usuwany, w celu zast pienia go przez poprzednik lub nast pnik w drzewie. Zło ono czasowa operacji usuwania klucza z B - drzewa jest taka sama (zarówno pesymistyczna jak i rednia) operacji wstawiania. 18 Przykład (t = 3) a) Pocz tkowe drzewo P C G M A B DEF T X JKL NO b) Po usuni ciu F: przypadek 1 QRS X UV YZ P C G M A B DE T X JKL NO c) Po usuni ciu M: przypadek 2a QRS X UV YZ P C G L A B DE T X JK NO d) Po usuni ciu G: przypadek 2c QRS X UV YZ P C L A B DEJK T X NO QRS X UV YZ 19 e) Po usuni ciu D: przypadek 3b C L P T X A B EJK QRS X NO UV YZ f) Po usuni ciu N: przypadek 3a C L Q T X A B EJK OP RS UV YZ Z definicji B - drzewa wynika, e s one wypełnione w co najmniej 50%. Mo e si wi c zdarzy , e 50% miejsca si w nich "marnuje". Analiza i symulacje wykazuj jednak, e po du ej liczbie losowych wstawie i usuni B - drzewo jest wypełnione w około 69%, a pó niejsze zmiany w proporcji zaj tego miejsca s ju bardzo niewielkie. To, e B - drzewo b dzie wypełnione całkowicie, jest równie mało prawdopodobne, celowe wi c wydaje si przyj cie dodatkowych warunków. 20 10. B* - drzewa B* - drzewo jest odmian B - drzewa wprowadzon przez Donalda Knutha, a nazwan tak przez Douglasa Comera. W B* - drzewie wszystkie w zły z wyj tkiem korzenia musz by wypełnione przynajmniej w dwóch trzecich, a nie tylko w połowie, jak w zwykłym B - drzewie. Dokładniej, liczba kluczy k, w nie b d cym korzeniem w le B* - drzewa, o minimalnym stopniu t spełnia warunek: 4t − 2 ≤ k ≤ 2t − 1 3 Cz sto rozdzielania w złów zmniejszamy, opó niaj c operacj rozdzielania, a w odpowiednim momencie rozdzielaj c dwa w zły na trzy zamiast jednego na dwa. Operacj rozdzielenia opó nia si , próbuj c przemieszcza klucze mi dzy w złem, a jego bratem, kiedy w zeł jest pełny. 21 Przykład (t = 4) a) Drzewo pocz tkowe K A B C F G H I M O R S T W Y b)Po wstawieniu E G O A B C E H I K M R S T W Y Zwró my uwag , e równo zostały podzielone nie tylko klucze, ale i wolne miejsca, dzi ki czemu w zeł, który jest pełny, mo e teraz pomie ci jeszcze jeden klucz. Je li brat pełnego w zła jest tak e pełny, to trzeba wykona operacj rozdzielania: tworzy si jeden nowy w zeł, klucze z w zła i jego brata (wraz z rozdzielaj cym je kluczem z ojca) s równo dzielone mi dzy trzy w zły, a dwa oddzielaj ce je klucze s umieszczane w ojcu. Wszystkie trzy w zły bior ce udział w operacji rozdzielania pozostaj wypełnione przynajmniej w dwóch trzecich. 22 11. B+ - drzewa Jak zrealizowa w klasycznym B - drzewie algorytm wypisania wszystkich kluczy w porz dku rosn cym? Mo na by u y łatwej do zaimplementowania metody inorder, ale dla wszystkich w złów wewn trznych byłby wypisywany jednorazowo tylko jeden klucz naraz, a potem nast pny krok wymagałby wczytania innego bloku. W B - drzewie odwołania do danych wyst puj w ka dym w le drzewa, natomiast w B+ - drzewie - jedynie w li ciach. Wewn trzne w zły B+ - drzewa słu jako indeksy umo liwiaj ce szybki dost p do danych; ta cz drzewa jest nazywana zbiorem indeksowym. Li cie s zazwyczaj poł czone w list . Przegl danie tej listy daje sekwencyjny dost p do danych. Wstawianie klucza do li cia, w którym jest jeszcze wolne miejsce, wymaga ustawienia kluczy w tym li ciu we wła ciwej kolejno ci. Nie zmienia si przy tym zbiór indeksowy. Je li klucz jest wstawiany do pełnego li cia, to li ten jest rozdzielany, nowy li jest wł czany do listy, klucze s rozdzielane równomiernie mi dzy stary i nowy li , a pierwszy klucz z nowego w zła jest kopiowany (a nie przemieszczany, jak w B - drzewie) do ojca jako separator pomi dzy tymi li mi. Je li ojciec nie jest pełny, mo e to wymaga lokalnej reorganizacji kluczy w tym w le. Nowy li jest tworzony i wł czany do listy, klucze s rozdzielane mi dzy te dwa li cie, a nowy separator zostaje skopiowany z nowego li cia do ojca. Je li ojciec jest pełny, to proces rozdzielania post puje jak w zwykłym B - drzewie - zbiór indeksowy jest przecie B - drzewem. 23 Przykład (t = 3) a) Drzewo pocz tkowe P ... G K A B D EF G H I K O b) Po wstawieniu C P ... D G K A BC DE F G H I K O Usuni cie klucza z li cia, je li nie powoduje wyst pienia niedoboru, ogranicza si do poprawienia ustawienia pozostałych kluczy w kolejno ci, bez zmian w zbiorze indeksowym. W szczególno ci, je li trzeba skasowa klucz wyst puj cy nie tylko w li ciu, to po prostu usuwa si go z li cia, ale pozostawia w w le wewn trznym. Powodem takiego post powania jest to, e klucz ten nadal pomaga znale wła ciw cie k podczas w drówki w dół B+ drzewa, poniewa wci poprawnie separuje klucze dwóch s siednich synów swojego w zła, chocia sam separator nie wyst puje w adnym z tych dwóch poddrzew. 24 Przykład a) Drzewo pocz tkowe P ... C F K A B CD F H I K O b) Po usuni ciu B P ... F K A C D F H I K O Je li usuni cie klucza z li cia powoduje niedobór, to albo klucze z tego li cia i jego brata s równo rozdzielane mi dzy te dwa w zły, albo li zostaje usuni ty, a jego pozostałe klucze s przenoszone do jego brata. Powy szy rysunek ilustruje ten ostatni przypadek. Po usuni ciu B pojawia si niedobór i dwa li cie s ł czone w jeden. Pierwszy klucz prawego s siada w zła powstaj cego po poł czeniu jest kopiowany do ojca, a klucze w ojcu s porz dkowane. Obydwie te operacje wymagaj uaktualnienia mieszcz cego si w ojcu klucza separuj cego dwa li cie. Usuni cie li cia mo e te wywoła seri zł cze w złów w zbiorze indeksowym. 25