10.4. Indices BTree Es un árbol con raı́z donde: Cada nodo x tiene: 1. N [x] número de claves 2. Las claves están ordenadas de menor a mayor k1 [x] < . . . < kn [x] 3. Una variable Boolean hoja[x] que es verdadera cuando el nodo x es una hoja. Si el nodo es interno, tiene n[x] + 1 punteros a hijos ki [x] separa los rangos que se almacenan las hojas están a la misma altura dado un t ≥ 2, nodos excepto la raı́z tiene t − 1 claves como mı́nimo y 2t − 1 claves como máximo. Ejemplo: Dibujo B-TREE del alfabeto con t = 3 P C A B D E F G T M J K L N O Q R S X U V Y Z Dado n ≥ 1, entonces cualquier n-key B-Tree de altura h y mı́nimo grado t2 satisface que h ≤ logt n+1 2 n ≥ 1 + (t − 1) ≥ 1 + (t − 1) ≥ 2th − 1 68 h ! 2ti−1 i=1 th " −1 t−1 # #nodos 1 1 t-1 t-1 t-1 / / / / / ...... t-1 ..... t-1 ..... t-1 t-1 k clave de búsqueda x nodo en el B-tree (inicialmente la raı́z leaf [x] indica si x es hoja n[x] indica numero de claves en el nodo ci [x] entrega puntero a hijo i en el nodo x Procedure BT REE SEARCH(k, x) i:= 1 while i ≤ n[x] and k > keyi [x] do i := i + 1 if i ≤ n[x] and k = keyi [x] then return (x, i) if leaf [x] the return nil else [ DISK READ(ci [x]) return BT REE SEARCH(k, ci [x])] end BT REE SEARCH Procedure BT REE SP LIT CHILD(x, i, y) / y es el i-ésimo hijo de x que es dividido z := Allocate N ode() leaf [z] := leaf [y] n[z] := t − 1 for j = 1 to t − 1 do keyj [z] := keyj+t [y] if not leaf [y] then for j = 1 to t do cj [z] := cj+t [y] n[y] := t − 1 for j = n[x] + 1 downto i + 1 do cj+1 [x] := cj [x] ci+1 [x] := z for j = n[x] downto i do keyj+1 [x] := keyj [x] keyi [x] := keyt [y] n[x] := n[x] + 1 DISK W RIT E(y) DISK W RIT E(z) DISK W RIT E(x) end BT REE SP LIT CHILD 69 2 t-1 t-1 2t Procedure BT REE IN SERT (T, k) r := root(T ) if n[r] = 2t − 1 then [ s := Allocate N ode() root[T ] := s leaf [s] := f alse n[s] := 0 c1 [s] := r BT REE SP LIT CHILD(s, 1, r) BT REE IN SERT N ON F U LL(s, k)] else BT REE IN SERT N ON F U LL(r, k) end BT REE IN SERT Procedure BT REE IN SERT N ON F U LL(x, k) i:= n[x] if leaf [x] then [ while i ≥ 1 and k < keyi [x] do [ keyi+1 [x] := keyi [x] i := i − 1] keyi+1 [x] := k n[x] := n[x] + 1 DISK W RIT E(x) else [ while i ≥ 1 and k < keyi [x] do i := i − 1 i:= i+1 DISK READ(ci [x]) if n[ci [x]] = 2t − 1 then [ BT REE SP LIT CHILD(x, i, ci [x]) if k > keyi [x] then i:= i+1] BT REE IN SERT N ON F U LL(ci [x], k) end BT REE IN SERT N ON F U LL 70 11. Heaps Una estructura heap puede ser vista como un árbol completo donde: A[P AREN T (i)] ≥ A[i] Usando una representación de arreglos de un árbol completo: P AREN T (i) return $i/2% LCHILD(i) return 2i RCHILD(i) return 2i + 1 Procedure BU ILD HEAP (A) heap size := length(A) for i = (length(A)/2 dowto 1 do HEAP IF Y (A, i) end BU ILD HEAP Procedure HEAP IF Y (A, i) l:= Left(i) r:= Right(i) if l ≤ heap size(A) and A[l] > A[i] then largest := l else largest : = i if r ≤ heap size(A) and A[r] > A[largest] then largest := r if largest &= i then [ exchange(A[i], A[largest]) HEAP IF Y (A, largest) ] end HEAP IF Y El costo computacional del algoritmo HEAPIFY de un subárbol de tamaño n y con raı́z i es de Θ(1) para encontrar la relación entre los elementos i, hijo izquierdo de i e hijo derecho de i, más el tiempo de ejecutar el HEAPIFY con un subárbol con la raı́z siendo uno de los hijos de i. Cada subárbol hijo tiene como máximo un tamaño 2n/3, con el peor caso cuando el último nivel está lleno a la mitad. Entonces el sistema recurrente del algoritmo HEAPIFY es: T (n) ≤ T (2n/3) + Θ(1) Con solución T (n) = O(logn) Para la función BUILD HEAP , se puede determinar un peor caso en forma simple. Hay un número de O(n) de llamadas a HEAPIFY con cada una de ellas de O(logn). Entonces, el BUILD HEAP tiene de orden O(nlogn). Un lı́mite más ajustado es por: 71 T (n) ≤ 0 ! k="logn# ' n 2 (O(k) = O(n k+1 1/2 ) = O(n) O(n (1 − 1/2)2 72 0 ! k="logn# k ) 2k