CLASIFICACIÓN POR ÁRBOL.Un montón se define como una secuencia de claves hL,hL+1,…,hR tales que hi h2i hi h2i+1 para i=L … R/2 Una forma de construir un montón in situ la ha propuesto R.W. Floyd .En ella se aplica el procedimiento sift(criba) . Se da un vector h1,….,hn; sin duda los elementos hm … hn (con m=(n DIV 2)+1)forman un montón , pues no hay 2 índices tales que j=2i ( o sea j=2i+1).Estos elementos constituyen lo que puede considerarse el renglón de parte inferior del árbol binario asociado , entre los que no se requiere ninguna relación de ordenación. El montón se amplía ahora a la izquierda , con lo cual en cada paso se incluye un nuevo elemento y se posiciona correctamente con un desplazamiento, es decir en la ordenación por montón existen 2 fases : -Construir un montón. -Ordenar el montón. h1 h2 h3 h5 h4 h6 h7 h12 h8 h9 h10 h11 h 1 = m in (h 1 ,h 2 ,....,h 1 5 ) La linea inferior es ya un montón h13 h14 h15 Construcción de un montón .El proceso de generar un montón de n elementos h1,…,hn in situ , es decir sin necesitar memoria extra; se describe así: L:=(n DIV 2) + 1; WHILE L>1 DO L:=L-1; CRIBA(L,n) END; PROCEDURE CRIBA(L,R:index); VAR i,j:index; x:item; BEGIN i:=L; j:=2*L; x:=a[L]; IF (j<R) & (a[j+1]<a[j]) THEN j:=j+1 END; WHILE (j<=R) & (a[j]<x) DO a[i]:=a[j]; (*ahora ver si después del intercambio se cumplen las condiciones del montón*) i:=j; j:=2*j; IF (j<R) & (a[j+1]<a[j]) THEN j:=j+1 END; END; a[i]:=x; (*colocar el elemento que se ha extraido anteriormente*) END CRIBA. Vamos a ver un ejemplo de construcción de un montón tenemos el vector a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] 44 55 12 42 94 18 06 67 L:=(8 DIV 2)+1; L:=5; WHILE 5>1 DO 4:=5-1; CRIBA(4,8); begin i:=4; j:=2*4=8; x:=a[4];(*primer paso*) 44 12 55 42 94 18 06 67 IF (8<8) & (a[9]<a[8]) THEN j:=j+1; (*esta sentencia no se ejecuta*) WHILE (j<=R) & (a[8]<a[4]) DO (*Este bucle no se ejecuta*) END a[i]:=x;a[4]:=42;(*es decir se queda como esta*) /*Siguiente pasada*/ L:=(8 DIV 2)+1; L:=5; WHILE 4>1 DO 3:=4-1; CRIBA(3,8); begin i:=3; j:=2*3=6; 12:=a[3];(*primer paso*) 44 12 55 42 06 18 94 67 IF (6<8) & (a[7]<a[6]) THEN j:=j+1; /*j:=7;*/ WHILE (7<=8) & (a[7]<a[3]) DO a[3]:=a[7] 44 06 55 42 94 18 12 67 i:=j; /*i:=7*/ las siguientes sentencias dentro del bucle no se cumplen END WHILE a[i]:=x; a[7]:=12; 1 44 3 2 06 55 4 5 42 7 6 12 18 94 8 67 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] 44 55 06 42 94 18 12 67 /*La segunda pasada*/ L:=(8 DIV 2)+1; L:=5; WHILE 3>1 DO 2:=3-1; CRIBA(2,8); begin i:=2; j:=2*2=4; 55=a[2];(*primer paso*) 1 44 3 2 06 55 4 5 42 94 7 6 18 8 67 IF (4<8) & (a[5]<a[4]) THEN j:=j+1; /*j:=4;*/ WHILE (4<=8) & (a[4]<a[2]) DO a[2]:=a[4] 12 1 44 3 2 06 42 4 55 12 18 94 67 i:=j; /*i:=4*/ j:=2*4; /*j=8) IF (j<8) & (a[8]<a[9]) THEN j:=j+1 /*no se ejecuta*/ END WHILE /*nos salimos del bucle*/ a[i]:=x; a[4]:=55; 1 44 3 2 06 42 4 55 94 18 12 67 a[1] a[2] a[3] a[4] 44 42 06 55 Ahora la tercera pasada L:=(8 DIV 2)+1; L:=5; WHILE 2>1 DO 1:=2-1; CRIBA(1,8); begin a[5] a[6] 94 18 a[7] a[8] 12 67 i:=1; j:=2*1=2; 44=a[1];(*primer paso*) 1 1 44 22 3 06 42 55 12 18 94 67 IF (2<8) & (a[3]<a[2]) THEN j:=j+1; /*j:=3;*/ WHILE (3<=8) & (a[3]<a[1]) DO a[1]:=a[3] 1 44 3 2 06 42 4 55 94 18 12 67 i:=j; /*i:=3*/ j:=2*3; /*j=6) IF (j<8) & (a[7]<a[6]) THEN j:=j+1 /*j:=7*/ END WHILE a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] 06 42 44 55 94 18 12 67 WHILE (7<=8) & (a[7]<a[1]) DO a[3]:=a[7] 1 06 3 2 44 42 4 55 12 18 94 67 END WHILE a[i]:=x; a[3]:=12; 1 06 3 2 12 42 4 55 94 18 44 67 a[1] 06 a[2] 42 a[3] a[4] 12 55 a[5] a[6] a[7] a[8] 94 18 44 67 Una vez realizado el último paso de cambiar el 44 por el 12 ya está construido el montón Ordenación por montón.Con objeto de obtener no sólo una ordenación parcial sino completa entre los elementos, han de realizarse n pasos de desplazamiento ; de ese modo déspues de cada paso el siguiente elemento (más pequeño) puede quitarse de la cima del montón. Una vez más se plantea la cuestión sobre el sitio donde guardar los elementos que emergen en la cima y si será posible o no la clasificación in situ. Desde luego hay esta solución : en cada paso se quita del montón el último componente (digamos x), se guarda el elemento de la cima del montón en la localización libre de x y se deja que x se desplace hacia abajo hasta alcanzar su posición correspondiente. El proceso se describe con ayuda del procedimiento Criba como sigue: R:=n; WHILE R>1 DO x:=a[1]; a[1]:=a[R]; a[R]:=x; R:=R-1; Criba(1,R); END; x a[1] a[2] a[3] a[8] 06 06 67 42 42 12 12 a[4] a[5] 55 55 94 94 a[6] 18 18 a[7] 44 44 67 06 1 06 3 2 12 42 4 55 44 18 94 67 IN T E R C A M B IA R primera pasada; R:=8; WHILE 8>1 DO x:=[a1];/*x=06*/ a[1]:=a[8];/*a[1]:=67*/ a[8]:=x;/*a[8]:=06*/ R:=8-1;R:=7 1 67 3 2 12 42 4 55 94 18 06 PROCEDURE CRIBA(1,7) VAR i,j:index; x:item; BEGIN i:=1; 44 j:=2*1; x:=a[1]; /*verificar las propiedades del montón y las condiciones de limite */ IF (2<7) & (a[3]<a[2]) THEN j:=3 END; WHILE (3<=7) & (a[3]<67 ) DO a[1]:=a[3];/*a[1]=12*/ i:=j;/*i=3*/ j:=2*j;/*j=6*/ IF (no se cumple esta sentencia) END a[3]:=67; 1 12 3 2 67 42 4 55 44 18 94 06 x a[8] 06 a[1] a[2] a[3] 06 12 42 42 12 67 a[4] a[5] 55 55 94 94 a[6] 18 18 La segunda pasada dentro del bucle WHILE; WHILE (6<=8) & (a[6]<67 ) DO a[3]:=a[6];/*a[3]=18*/ i:=j;/*i=6*/ /*se sale del vector*/ a[7] 44 44 67 06 x a[8] 06 END a[6]:=67; a[1] a[2] 06 12 42 42 1 a[3] 12 18 a[4] a[5] 55 55 94 94 12 3 2 18 42 4 55 67 94 44 06 La segunda pasada R:=8; WHILE 7>1 DO x:=[a1];/*x=12*/ a[1]:=a[7];/*a[1]:=44*/ a[7]:=x;/*a[7]:=12*/ R:=7-1;R:=6 1 44 3 2 18 42 4 55 06 94 67 12 a[6] 18 67 a[7] 44 44 67 06 PROCEDURE CRIBA(1,6) VAR i,j:index; x:item; BEGIN i:=1; j:=2*1; x:=a[1]; /*verificar las propiedades del montón y las condiciones de limite */ IF (2<6) & (a[3]<a[2]) THEN j:=3 END; WHILE (3<=6) & (a[3]<44 ) DO a[1]:=a[3];/*a[1]=18*/ i:=j;/*i=3*/ j:=2*j;/*j=6*/ IF (no se cumple esta sentencia) END a[3]:=44; 1 18 3 2 44 42 4 55 94 12 67 06 x a[8] 06 a[1] a[2] 06 42 18 42 WHILE 6>1 DO x:=[a1];/*x=18*/ a[3] 12 44 a[4] a[5] 55 55 94 94 a[6] 18 67 a[7] 44 12 67 06 a[1]:=a[6];/*a[1]:=67*/ a[6]:=x;/*a[6]:=18*/ R:=6-1;R:=5 1 67 3 2 44 42 4 55 94 18 12 06 PROCEDURE CRIBA(1,5) VAR i,j:index; x:item; BEGIN i:=1; j:=2*1; x:=a[1]; /*verificar las propiedades del montón y las condiciones de limite */ IF (2<5) & (a[3]<a[2]) THEN no se ejecuta END; WHILE (2<=6) & (a[2]<67 ) DO a[1]:=a[2];/*a[1]=42*/ i:=j;/*i=2*/ j:=2*j;/*j=4*/ IF (no se cumple esta sentencia) END 1 42 3 2 44 55 4 67 94 18 12 06 segunda pasada dentro del bucle WHILE WHILE (4<=6) & (a[4]<67 ) DO a[2]:=a[4];/*a[2]=55*/ i:=j;/*i=4*/ j:=2*j;/*j=8*/ IF (no se cumple esta sentencia) END; a[4]=67; x a[1] a[2] a[3] a[4] a[5] a[6] 06 06 42 12 55 94 18 42 55 44 67 94 18 y así sucesivamente hasta llegar a[1] a[2] a[3] a[4] a[5] 06 42 12 55 94 94 67 55 44 42 a[6] 18 18 a[7] 44 12 a[8] 67 06 a[7] 44 12 a[8] 67 06 Análisis: -La eficiencia crece al crecer n -Para n pequeño es poco eficiente -En el peor caso , hay n/2 desplazamientos, pasando los elementos por log(n/2),log(n/2-1), ….,log(n) posiciones.Déspues la fase de clasificación hace n-1 desplazamientos,con un máximo de log(n-1),log(n-2),…,1 movimientos .Además hay n-1 movimientos para guardar a la derecha el elemento desplazado . -Por lo tanto toma del orden n*logn pasos en el peor caso posible -El número promedio de movimientos es en torno n/2*logn y las desviaciones respecto a este valor son relativamente pequeñas