mrgsrt.pas
{ ppc386 -va -vh *.pas }
{ COMIENZO DE DESCRIPCION
El algoritmo Mergesort modificado. El procedimiento Mergesort
se basa en la estrategia "dividir para vencer". Primero se
ordenan las posiciones impares entre si (recursivamente),
luego las pares y, finalmente, se intercalan ambas
subsecuencias. Si el intercalamiento se puede hacer en
tiempo $O(n)$ entonces puede demostrarse que el n\'umero de
operaciones total es $O(n log(n))$ en el peor caso. Ya hemos
visto para la representaci\'on de conjuntos como listas
enlazadas clasificadas que el intercalamiento de dos listas
enlazadas clasificadas se puede hacer en tiempo $O(n)$.
Para vectores no es tan sencillo, y se conjetura que no se
puede hacer tal operaci\'on en tiempo $O(n)$ sin uso de
memoria adicional (es decir, no se puede hacer "in place").
Escriba un `procedure MERGEQ (var A:vector; N:tipo_elemento);'
que ordena un vector cuyas posiciones pares e impares
est\'an ordenadas entre si, usando una cola auxiliar.
[Tomado en el 3er parcial 2002 (25 de junio de 2002)]
keywords: clasificacion
FIN DE DESCRIPCION
}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ Se propone el siguiente algoritmo de intercalaci\'on para
vectores que utiliza una cola auxiliar $C$ (y por lo tanto
no es "in place"). Por simplicidad asumimos que el n\'umero
de elementos en el arreglo $n$ es par, que las posiciones
impares y pares est\'an clasificadas entre si y que,
inicialmente, la cola $C$ est\'a vacia. Considerando el
arreglo $A$ de longitud $n=16$ de la figura, el algoritmo
lo ordena en $n/2=8$ pasos. En cada paso el algoritmo ordena
los elementos $p,q$ en las posiciones $2j-1$ y $2j$.
Despu\'es del paso $j$ los primeros $2j$ elementos est\'an
ordenados y ubicados en parte en la cabecera del vector
(posiciones 1 a $k$, marcados en la figura con una caja
rectangular) y en la cola $C$. Entre la posici\'on $k+1$ y
la posici\'on $2j-1$ hay una serie de elementos (tantos como
hay en $C$) cuyos valores son irrelevantes (en la figura
est\'an marcados con una $X$). El algoritmo es el siguiente
%
for j:=1 to n div 2 do begin
p := A[2j-1]; q := A[2j]; r := min(p,q);
poner max(p,q) en C;
poner todos los elementos de C menores o iguales que r
en la cabecera de A (despues de la posicion k);
poner r en la cabecera de A;
end;
poner todos los elementos restantes de C en la cabecera
de A;
Se puede ver que el tama\~no de la cola es $O(\sqrt n )$,
m\'as precisamente $\approx 0.82sqrt n$. }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{$ Id: mrgsrt.pas 2003/06/19 14:00:00 mstorti Exp jdelia $ }
program mrgsrt_p;
uses u_colapi;
const N = 128;
type
cola = colapi;
vector = array[1..N] of integer;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ Intercala dos secuencias en un vector comenzando en la
posicion "com" y con intervalos "d". Las posiciones pares
(es decir, "com+d", "com+3d", ...) estan ordenadas entre si.
Las posiciones impares tambien. Se utiliza una cola auxiliar}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure merge (var A: vector;
var C: cola;
com, d, n: integer);
var
i, k, aa, b, min, j : integer;
begin
k := com;
j := com;
{ pa(A,com,n,d); } { descomentar para ver como funciona }
for i := 1 to n do begin
aa := A [j];
{ Pone el maximo de `p,q' en la cola }
b := A [j + d];
if (aa < b) then begin
min := aa;
C.PONE (b); end
else begin
min := b;
C.PONE (aa);
end; {if}
j := j + 2 * d;
while (not C.VACIA) and (C.FRENTE < min) do begin
A [k] := C.FRENTE;
C.QUITA;
k := k + d;
end ; {while}
A [k] := min;
k := k+d;
{ pa (A,com,n,d); } { descomentar para ver como funciona }
end; {i}
while not C.VACIA do begin
A [k] := C.FRENTE;
C.QUITA;
k := k + d;
end; {while}
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure pa (A: vector; com,n,d: integer);
var
i, j : integer;
begin
j := com;
for i := 1 to n do begin
write ( A[j],' ');
j := j + d;
end; {i}
writeln;
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ Esta es una rutina auxiliar. Ordena "n" elementos de
un vector, desde la posicion "com" cada "d", es decir
los elementos com, com+d, etc... Las posiciones pares y
las impares ya estan ordenadas entre si. }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure MRGSRT1 (var A: vector;
var C: cola;
com, d, n: integer);
begin
if (n > 1) then begin
MRGSRT1 (A, C, com , 2*d, n div 2);
MRGSRT1 (A, C, com+d, 2*d, n div 2);
MERGE (A, C, com , d, n div 2);
end; {if}
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ Este es un "wrapper" para evitar los argumentos "com"
y "d". Define la cola auxiliar "C". }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure MRGSRT (var A :vector; n : integer);
var
C : cola;
begin
C.ANULA ;
MRGSRT1 (A, C, 1, 1, n);
end;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
var
A : vector;
j, M: integer;
begin
M := 100; {inicialmente llenado con numeros aleatorios}
randomize ;
for j := 1 to N do begin
A [j] := random (M);
end;
pa (A,1,n,1); { Imprime vector }
mrgsrt (A,N); { Ordena }
pa (A,1,n,1); { Imprime vector ordenado }
end.
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
Generated by GNU enscript 1.6.1.