Ordenación por montón

Anuncio
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
Descargar