Estoy leyendo un análisis sobre matrices dinámicas (del manual de algoritmos de Skiena).
Es decir, cuando tenemos una estructura de matriz y cada vez que nos quedamos sin espacio, asignamos una nueva matriz del doble del tamaño del original.
Describe el desperdicio que ocurre cuando la matriz tiene que ser redimensionada.
Dice que (n / 2) +1 a n se moverán como máximo una vez o no se moverán. Esto esta claro.
Luego, al describir que la mitad de los elementos se mueven una vez, una cuarta parte de los elementos dos veces, y así sucesivamente, el número total de movimientos M viene dado por:
Esto me parece que agrega más copias de las que realmente suceden.
P.ej
si tenemos lo siguiente:
array of 1 element
+--+
|a |
+--+
double the array (2 elements)
+--++--+
|a ||b |
+--++--+
double the array (4 elements)
+--++--++--++--+
|a ||b ||c ||c |
+--++--++--++--+
double the array (8 elements)
+--++--++--++--++--++--++--++--+
|a ||b ||c ||c ||x ||x ||x ||x |
+--++--++--++--++--++--++--++--+
double the array (16 elements)
+--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+
|a ||b ||c ||c ||x ||x ||x ||x || || || || || || || || |
+--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+
Tenemos el elemento x copiado 4 veces, el elemento c copiado 4 veces, el elemento b copiado 4 veces y un elemento copiado 5 veces, por lo que el total es 4 + 4 + 4 + 5 = 17 copias / movimientos.
Pero de acuerdo con la fórmula, deberíamos tener 1 * (16/2) + 2 * (16/4) + 3 * (16/8) + 4 * (16/16) = 8 + 8 + 6 + 4 = 26 copias de elementos para la ampliación de la matriz a 16 elementos.
¿Es esto un error o el objetivo de la fórmula es proporcionar una aproximación aproximada del límite superior? ¿O estoy entendiendo mal algo aquí?
fuente
b
se copia 3 veces, cadac
dos veces y cadax
una. 15 ejemplares.Respuestas:
En primer lugar, b se mueve 3 veces y a se mueve 4 veces, lo que da un total de 4 + 4 + 3 + 4 = 15 copias.
Creo que la fórmula se debe completar con n = 8: 1 * (8/2) (x se copia una vez) + 2 * (8/4) (c se copia dos veces) + 3 * (8/8) (b se copia tres veces) = 11. En otras palabras, a la fórmula parece faltarle un término "+ log 2 n + 1" además de la suma misma.
Lo que me parece una forma mucho más natural de contar el número de movimientos es contar el número de elementos movidos por copia:
suma de i = 1 a i = techo (log 2 n): 2 i-1
En su caso, n = 16, entonces techo (log 2 16) = 4 y la suma anterior es: 2 0 +2 1 +2 2 +2 3 = 1 + 2 + 4 + 8 = 15.
Veré si puedo encontrar el manual de algoritmos de este Skiena para ver si lo tengo correcto.
Actualización: encontré la parte en el manual del algoritmo de Skiena. Parece que falta un término en la suma que usa allí. Sin embargo, la conclusión es correcta:
M = suma de i = 1 a i = techo (log 2 n): 2 i-1 = suma de i = 0 a i = techo (log 2 n) - 1: 2 i = 2 techo (log 2 n) - 1 + 1 <= (2 log 2 n + 1 - 1 + 1 ) = 2 * n
(Desearía poder formatear estas fórmulas de una manera más agradable para ti)
El punto principal de este párrafo parece ser dar un ejemplo de análisis amortizado . Métodos como el método potencial podrían hacer un argumento mejor (menos ad hoc) por qué los arreglos dinámicos funcionan muy bien, pero este método es algo avanzado.
Si está convencido de que hay un error en este libro, podría considerar ponerse en contacto con el autor al respecto (de una manera constructiva, por supuesto, el libro tiene muchas páginas y es difícil corregir hasta el último detalle, y siempre hay un posibilidad de que el libro sea correcto y los dos nos equivoquemos). No he encontrado este en particular en la errata.
fuente
En los niveles más bajos de conteo de bloques, es poco probable que ocurra una asignación de memoria. Los administradores de memoria manejan bloques de memoria y asignan rutinariamente bloques de memoria más grandes que la solicitud de asignación solicitada actualmente.
Del mismo modo, es probable que la implementación de una clase de matriz redondee las asignaciones para permitir algunos elementos adicionales.
EDITAR:
En una reflexión posterior, es poco probable que las copias reales ocurran como las describe. Los procesadores generalmente tienen un comando de copia en bloque y usarían una sola instrucción de ensamblador para copiar los datos de la matriz como un solo bloque de memoria a la nueva dirección.
fuente
Creo que la fórmula dada en el libro es simplemente incorrecta. El
i
multiplicador debe eliminarse de la fórmula para solucionarlo.Tomemos el ejemplo del autor de la pregunta y llamemos a la matriz de 1 elemento matriz-1, la matriz de 2 elementos -
array-2
, la matriz de 4 elementos -array-4
, y así sucesivamente.Entonces, de acuerdo con el libro, para este ejemplo en particular, el número de copias se rige por la siguiente fórmula:
El primer término de la suma
1⋅8
es para copiararray-8's
elementos enarray-16
.Copiamos los
array-4's
artículos(a, b, c, c)
dos veces. Una vez delarray-4
alarray-8
. Y luego, al copiararray-8's
elementosarray-16
, copiamos(a, b, c, c)
elementos por segunda vez. De acuerdo con el libro, por lo tanto, el segundo término:2⋅4
.Pero ahora observe que el
1⋅8
término ya tiene en cuenta la copia de(a, b, c, c)
elementos dearray-8
aarray-16
. En consecuencia, el2⋅4
término no debe incluir el2
multiplicador.La misma lógica se aplica a todos los demás términos. Y multiplicar por
i
es un error.fuente
M=1⋅8+2⋅4+3⋅2+4⋅1
etc