Clase de sorting - Departamento de Computación

Anuncio
Ordenamiento
Algoritmos y Estructuras de Datos 2
Departamento de Computación,
Facultad de Ciencias Exactas y Naturales,
Universidad de Buenos Aires
Mayo de 2015
Funciones auxiliares
unirListasDeArreglo(in A: arreglo(lista(alumno)), out B : arreglo(alumno))
lista(α) B ← Vacı́a()
for i ← 0 to tam(A − 1) do
unirListas(B, A[i])
end for
O(1)
O(|A[i]|)
Complejidad del algoritmo: O(1) + O(|A[0]|) + O(|A[1]|) + ... + O(|A[9]|) =
O(1) +
P9
i=0
O(|A[i]|) =
P9
i=0
O(|A[i]|) = O(n) (Como mucho hay n hombres o n mujeres)
unirListas(inout IZQ: lista(α), inout DER : lista(α) )
for i ← 0 to Longitud(DER − 1) do
AgregarAtras(IZQ, Copiar(A[0]))
Fin(DER)
end for
O(copy(α))
O(1)
Complejidad del algoritmo: O(|DER| ∗ |α|)
deListaAArreglo(inout A: lista(α), out B : arreglo(α) )
arreglo(α) B ← crearArreglo(Longitud(A))
for i ← 0 to Longitud(A − 1) do
B[i] ← A[0]
Fin(A)
end for
O(|A|)
O(copy(α))
O(1)
Complejidad del algoritmo: O(|A| ∗ |α|)
1
unirArreglos(in A: arreglo(α), in B: arreglo(α), in C: arreglo(α) out R : arreglo(α) )
arreglo(α) B ← crearArreglo(Longitud(A) + Longitud(B) + Longitud(C))
nat idx ← 0
for i ← 0 to Longitud(A − 1) do
R[idx] ← A[i]
idx ← idx + 1
end for
for i ← 0 to Longitud(B − 1) do
R[idx] ← B[i]
idx ← idx + 1
end for
for i ← 0 to Longitud(C − 1) do
R[idx] ← C[i]
idx ← idx + 1
end for
Complejidad del algoritmo: O((|A| + |B| + |C|) ∗ copy(α))
2
O(|A| + |B| + |C|)
O(1)
O(copy(α))
O(copy(α))
O(copy(α))
Primer ejercicio
Considere la siguiente estructura para guardar las notas de un alumno de un curso:
alumno es tuplahnombre: string, sexo: FM, puntaje: Notai
donde FM es enum{masc, f em} y Nota es un nat no mayor que 10.
Se necesita ordenar un arreglo(alumno) de forma tal que todas las mujeres aparezcan al inicio de la tabla según
un orden creciente de notas y todos los varones aparezcan al final de la tabla también ordenados de manera creciente
respecto de su puntaje, como muestra en el siguiente ejemplo:
Entrada
Ana
F
Juan M
Rita
F
P aula F
Jose
M
P edro M
Salida
Rita
F
6
P aula F
7
Ana
F 10
Juan M
6
Jose
M
7
P edro M
8
10
6
6
7
7
8
Proponer un algoritmo de ordenamiento ordenaPlanilla(inout p: arreglo(alumno)) para resolver el problema
descripto anteriormente y cuya complejidad temporal sea O(n) en el peor caso, donde n es la cantidad de
elementos del arreglo. Justificar.
ordenaPlanilla(inout A: arreglo(alumno))
arreglo(lista(alumno)) F emenino ← crearArreglo(10)
arreglo(lista(alumno)) M asculino ← crearArreglo(10)
for i ← 0 to 9 do
F emenino[i] ← Vacı́a()
M asculino[i] ← Vacı́a()
end for
for i ← 0 to tam(A − 1) do
if A[i].sexo = F then AgregarAtras(F emenino[A[i].nota − 1], A[i])
else AgregarAtras(M asculino[A[i].nota − 1], A[i]) end if
end for
lista(alumno) M ujeres ← unirListasDeArreglo(F emenino)
lista(alumno) Hombres ← unirListasDeArreglo(M asculino)
A ← deListaAArreglo(unirListas(M ujeres, Hombres))
Complejidad del algoritmo: O(n) + O(n) + O(n) + O(n) = O(n) donde n = |A|.
3
O(10) = O(1)
O(10) = O(1)
O(1)
O(1)
O(1)
O(1)
O(n)
O(n)
O(n)
Segundo ejercicio
Se desea ordenar los datos generados por un sensor industrial que monitorea la presencia de una sustancia en un
proceso quı́mico. Cada una de estas mediciones es un √
número entero positivo. Dada la naturaleza del proceso se sabe
que, dada una secuencia de n mediciones, a lo sumo b nc valores están fuera del rango [20, 40].
Proponer un algoritmo O(n) que permita ordenar ascendentemente una secuencia de mediciones y justificar la
complejidad del algoritmo propuesto.
ordenarDatos(inout A: arreglo(nat))
lista(nat) menoresA20 ← Vacı́a()
lista(nat) entre20Y 40 ← Vacı́a()
lista(nat) mayoresA40 ← Vacı́a()
for i ← 0 to tam(A − 1) do
if A[i] < 20 then AgregarOrdenado(menoresA20, A[i])
else if A[i] < 41 then AgregarAtras(entre20Y 40, A[i])
else AgregarOrdenado(mayoresA40, A[i]) end if
end for
arreglo(nat) X ← deListaAArreglo(entre20y40)
CountingSort(X)
arreglo(nat) Xmen ← deListaAArreglo(menoresA20)
arreglo(nat) Xmay ← deListaAArreglo(mayoresA40)
A ← unirArreglos(Xmen, X, Xmay)
O(1)
O(1)
O(1)
√
O( n) = O(|menoresA20|)
O(1)
√
O( n) = O(|mayoresA40|)
O(n) = O(|entre20Y 40|)
√ O(n) = O(|X| + 40)
O(√n) = O(|menoresA20|)
O( n) = O(|mayoresA40|)
O(n)
√
Los números menores a 20 o mayores a 40 son a lo sumo n. Luego, para calcular la complejidad final del ciclo
principal, multiplicamos el costo de cada rama del condicional,
√ por la cantidad de veces que entramos a√esa rama. Por
n)
ejemplo, el costo de procesar un número menor
que
20
es
O(
√ √
√ pero
√ sólo voy a tener que hacerlo O( n) veces.
Finalmente, la complejidad del ciclo es O( n · n + n · 1 + n · n) = O(n + n + n) = O(n).
Podemos aplicar CountingSort en X porque sabemos que los valores de las mediciones en este arreglo están entre
20 y 40.
4
Tercer ejercicio
Se tienen k arreglos de naturales A0 , ..., Ak−1 . Cada uno de ellos está ordenado de forma creciente. Además, se
sabe que para todo i el arreglo Ai tiene exactamente 2i elementos.
Pk−1
Dar un algoritmo que devuelva un arreglo B de n = i=0 2i = 2k − 1 elementos, ordenado crecientemente, de
manera que contenga a todos los elementos de los A[i], contando repeticiones. El algoritmo debe tener complejidad
O(n).
granMerge(in A: arreglo(arreglo(nat)), out B : arreglo(nat) )
arreglo(nat) B ← crearArreglo(0)
for i ← 0 to tam(A − 1) do
merge(B, B, A)
end for
O(1)
O(2i ) = O(2i + (2i − 1)) = O(tam(B) + tam(A))
El merge utilizado es el especificado en el apunte de algoritmos básicos. El algoritmo tiene complejidad
O(n) = O(2k − 1) = O(
Pk−1
i=0
2i ) =
Pk−1
i=0
O(2i )
que es la suma de las complejidades de cada iésima iteración, calculadas según la complejidad que tiene el merge del
apunte.
5
Descargar