Sei sulla pagina 1di 19

Ordenamiento de listas -

Juego Josephus Flavius


Agenda

1. Ordenamiento de listas enlazadas.


2. El juego de Josephus Flavius.

2
Ordenamiento de listas enlazadas
• Supongamos que tenemos una lista enlazada ordenada. Ahora pensemos
en las operaciones básicas.

Ordenamiento
listas enlazadas ¿Qué tendríamos que hacer para agregar un elemento a la lista?
Juego Josephus
Flavius
1. Encontrar la ubicación correcta.
¿Cuál seria la eficiencia? O(n)
2. Agregar el elemento.

Proceso muy similar y


¿Y que tal borrar un elemento? misma eficiencia O(n)

3
Comparación ordenada – no ordenada
Estructura Inserción Indexación Búsqueda Borrado
Lista enlazada O(n) O(n) O(n) O(n)
desordenada
Excepto que Excepto que Excepto que ¿Entonces para
sea al inicio o sea el primero sea el primero que sirve ordenar
Ordenamiento al final de la o el último, en o el último, en una lista
listas enlazadas lista, en cuyo cuyo caso es cuyo caso es
caso es O(1) O(1) O(1) enlazada?

Juego Josephus
Lista enlazada O(n) O(n) O(n) O(n)
ordenada
Flavius

Pueden existir problemas específicos que requieran el uso de una lista enlazada ordenada.

Por ejemplo:
(i) mostrar los elementos de manera ordenada.
(ii) cuando se requiere acceder constantemente a los X menores y/o X mayores elementos.
(iii) se podría diseñar un algoritmo de búsqueda binaria con punteros a ciertas posiciones, pero es difícil de
mantener.
4
Ordenamiento de listas enlazadas - II
• Continuando con el problema, entonces ¿Cómo hacemos para ordenar
una lista enlazada?

Ordenamiento
listas enlazadas • Básicamente, igual que con los arreglos, hay dos caminos a seguir:
Juego Josephus 1. Si ya se tiene la lista, y este está desordenada, se puede ordenar usando un
Flavius algoritmo de ordenamiento.
2. Si se parte de una lista vacía, se puede ir insertando progresivamente cada
elemento en el lugar que le corresponde.

5
Algoritmo de ordenamiento bubleSort
LinkedList<Integer> L = new LinkedList<Integer>(); ¿Cuál seria la
Scanner entrada = new Scanner(System.in); eficiencia?
int N = entrada.nextInt();
for (int i = 0; i < N; i++) {
Ordenamiento L.add(entrada.nextInt()); O(N^3)
listas enlazadas
}
int aux; ¿Cómo
Juego Josephus
for (int i = 1; i < N; i++) { mejorarlo?
Flavius
for (int j = 0; j < N - i; j++) {
if (L.get(j) > L.get(j + 1)) {
aux = L.get(j); Se podría utilizar un
L.set(j, L.get(j + 1)); iterator y mejorar la
L.set(j + 1, aux); eficiencia hasta
} O(N^2)
}
}

6
Algoritmo de ordenamiento progresivo
LinkedList<Integer> L = new LinkedList<Integer>();
Scanner entrada = new Scanner(System.in);
Iterator<Integer> it; ¿Cuál seria la
int j; eficiencia?
int x = 0;
Ordenamiento int N = entrada.nextInt(); O(N^2)
listas enlazadas L.add(entrada.nextInt());
for (int i = 1; i < N; i++) {
Juego Josephus x = entrada.nextInt();
Flavius it = L.listIterator();
j = 0;
while (it.hasNext()) {
if (it.next() < x) {
j++;
} else {
break;
}
}
L.add(j, x);
}
7
Algoritmo de ordenamiento mergeSort
• ¿Cómo seria la eficiencia de este
algoritmo en el caso de las listas
enlazadas?
Ordenamiento
listas enlazadas
• Resulta que, aunque un tanto más
Juego Josephus
Flavius complicado de programar que en el
caso de arreglos, el mismo
O(N*log(N)).

8
El juego de Josephus Flavius
“Para sobrevivir, un buen soldado debe ante todo saber pensar”

Ordenamiento
listas enlazadas

Juego Josephus
Flavius

9
• Josephus Flavius fue un famoso historiador judío del
siglo I. Durante la guerra judío-romana fue rodeado
por el ejército romano y quedó atrapado junto a 40
soldados en una cueva.
• La leyenda dice que, prefiriendo el suicido a la
captura, los soldados decidieron formar un círculo.
Luego se numeraron del 1 al 41 (para incluir a
Ordenamiento Josephus).
listas enlazadas
• Comenzando con el soldado 1, contaban 3 soldados
Juego Josephus
y ese debía ser asesinado por el compañero de la
Flavius izquierda. El proceso se repetía a partir de allí hasta
que no quedara sino uno en pie (al último no había
quien lo matara).
• Josephus no quería morir y por eso hizo un rápido
ejercicio mental, encontró el “puesto seguro” y
escapó de la muerte (los romanos al ver la masacre
y que era el único sobreviviente lo dejaron con
vida).

10
Simulación

Ordenamiento
listas enlazadas

Juego Josephus
Flavius

11
El juego de Josephus Flavius - II
• Basado en hechos reales …

Ordenamiento • En su entrevista para una de las más importantes empresas de software


listas enlazadas del mundo a un estudiante de la nacho le pidieron: “Diseñe un algoritmo
Juego Josephus
para determinar el “puesto seguro” en el juego de Josephus considerando
Flavius n jugadores y un conteo de k para eliminar un jugador (n y k son enteros
positivos)”.

12
Solución A
• Creamos un arreglo X de n números enteros, en la posición 0 ponemos el
“1”, en la 1 el “2” y así sucesivamente hasta “n”.
pos = 0;
cantidadJugadores = n; ¿Cómo encontrar
while (cantidadJugadores > 1) { el sobreviviente?
Ordenamiento contador = 0;
listas enlazadas while (contador < k) {
if (pos == n) {
Al terminar el while más
Juego Josephus pos = 0;
Flavius externo buscamos la única
}
posición que no valga -1 y
if (X[pos] != -1) {
esa es la solución
contador++;
}
pos++;
}
X[pos-1] = -1;
cantidadJugadores--;
}

13
Solución A – II
Objeción del entrevistador: ¿cuál es la eficiencia del algoritmo
en términos de n y k?, ¿qué pasaría si son muy grandes?

Ordenamiento
• Como no se puede simplemente saltar en el arreglo k
listas enlazadas posiciones hacia la derecha pues no se sabe cuantos en el
medio han muerto, “matar uno” no es O(1) .
Juego Josephus
Flavius
• Encontrar la siguiente posición “no muerto” puede ser O(n)
en el peor de los casos, por tanto encontrar la posición k-
ésima puede ser O(nk), y eso es solo para matar uno.

• Entonces matar n-1 tomaría O((n^2)k) ¿Cómo


mejorarlo?
• Si n es por ejemplo un millón y k es quinientos mil, eso daría
… 500.000.000.000.000.000 (5E+17)
14
Solución B
• Creo una lista enlazada L, agrego un “1”, luego un “2” y así sucesivamente
hasta “n”.

Ordenamiento pos = 0; ¿Cómo encontrar


listas enlazadas while (L.size() > 1) {
el sobreviviente?
contador = 0;
Juego Josephus while (contador < k) {
Flavius if (pos == L.size()) {
pos = 0; Al finalizar accedemos a la
} lista L.get(0)
pos++;
contador++;
}
L.remove(pos-1);
pos--;
}

15
Solución B - II
• Como ya se trata de una lista donde solo están
jugadores vivos matar al k siguiente implica: el
while más interno que es O(k), más el remove que
es O(n).
Ordenamiento
listas enlazadas
• Entonces matar n-1 tomaría O(n(n+k)) … Si, otra
Juego Josephus vez, n es por ejemplo un millón y k es quinientos
Flavius mil, eso daría … 1.500.000.000.000 (1,5E+12)
Objeción del entrevistador: ¿No se
• Le quitamos unos cuantos ceros. puede hacer mejor considerando que si
en algún momento k es mayor que la
cantidad de jugadores con vida estaría
mmm … tiene razón, si por ejemplo no quedan sino 10 dando vueltas “innecesarias”?
jugadores y k es 25 habría que dar dos vueltas y media,
en vez de simplemente moverse 5 posiciones desde
donde esté parado. Si k es mucho más grande que n,
peor aún!
16
Solución C
• Creo una lista enlazada L, agrego un “1”, luego un “2” y así sucesivamente
hasta “n”.

pos = 0; Este algoritmo se podría


while (L.size() > 1) { mejorar un poco más
Ordenamiento contador = 0; realizando el siguiente
listas enlazadas while (contador < k%L.size()) { cambio
if (pos == L.size()) {
Juego Josephus pos = 0;
Flavius } pos = 0;
pos++; while (L.size() > 1) {
contador++; contador = 0;
} pos = (pos + k - 1)%L.size();
L.remove(pos-1); L.remove(pos);
pos--; }
} L.get(0);
L.get(0);

17
Solución C – II
• El algoritmo anterior garantiza O(n) en el
while y un O(n) del remove interior, por lo
tanto seria en total O(n^2).
Ordenamiento
listas enlazadas
• Siendo así, O(n(n+k)) de la solución B se
Juego Josephus
Flavius convierte en O(n^2) para la solución C.

• En otras palabras: ya no importa que k sea


grande. Si por ejemplo n es 20 y k es un
millón, eso daría solo 400, comparado con
los 20 millones de la solución anterior.

18
Referencias
• Liang, Y. D. (2015). Introduction to Java programming, comprehensive.
Pearson Higher 10th Edition -> Chapters 20 and 24.
• Aguilar, L. J., & Zahonero, I. (2007). Estructuras de datos en Java. McGraw-
Hill/Interamericana de España -> Capítulo 8.
• Material del curso de Estructuras de Datos del profesor Julián Moreno.
• Simulación https://www.geogebra.org/m/ExvvrBbR

Estructuras de Datos 19

Potrebbero piacerti anche