Programación General > Visual Basic para principiantes
¿Cómo redimensionar una matriz dentro de otra matriz?
m0skit0:
Nebire, como siempre, me quito el sombrero ;) :good:
Por cierto, deaven, si te interesa calcular el tiempo que tarda en ejecutarse una parte del código, te aconsejo que le eches un vistazo a esto, seguro que te viene muy bien (porque yo también lo tuve que hacer :)):
--- Código: Visual Basic ---Private Declare Function timeGetTime Lib "winmm.dll" () As Long Private Sub TalyCual(ByLoQueSea Parametro As TipoLoQueSea) Dim Tiempo_Inicial As Long Tiempo_Inicial = timeGetTime() 'Procesamos... Debug.Print timeGetTime - Tiempo_InicialEnd Sub Ah y otro consejo: evita el uso de cadenas de caracteres todo lo que puedas. La lentitud de su procesamiento es uno de los mayores defectos de VB6 :bad:
Saludos y espero que te sirva
Nebire:
Deaven debes tener en cuenta algunas cosillas para acelerar tanto trasiego.
Si como dices una matriz de repente tienes que aumentarla al doble de su tamaño, entiendo que o bien haces un trasvase de información procedente de dos matrices de idéntico tamaño, o bien entiendo que estás reservando espacio de una sola vez para que no se agote rápidamente y tengas contínuamente que que redimensionar las matrices. Si esto es así, es posible que te vaya mejor una colección.
Una matriz es más rápida que una colección cuando el número de elementos no va a superar nunca algo así como 100 a partir de ese tamaño una colección suele ser más eficiente, añades y quitas elementos dinámicamente por lo que no malgastas memoria, esto es no utilizas más espacio del que justamente necesitas a cada instante.
Ahora bien una colección es un poco limitada, no permite muchas cosas, sin embargo puedes utilizarla para crear clases que utilicen la colección como base añadiendo métodos.
No obstante si (como supongo) el código lo estás usando para el programa de inteligencia artificial, creo que sería más acertado que en determinadas circunstancias usaras árboles. en VB6 es relativamente fácil implementar cualquier tipo de árbol. Por ejemplo posiblemente te sería muy útil el arbol de tipo 'montículos' ya que supongo que muchas de las acciones que realices se basarán en cuestiones de prioridad. Los montículos también son óptimos para ordenar y además los montículosm permiten pasarlo a una matriz o crear un montículo desde una matriz en un tiempo prácticamente lineal.
Es difícil determinar que tipo de árbol irá mejor para cada cosa, porque desconocemos los detalles del uso que le das a cada matriz.
En cualquier caso si usas matrices ten en cuenta el siguiente consejo:
Cuando utilices varias veces seguidas el mismo índice de una matriz es más rápido usar una variable. Pongo un ejemplo y lo pruebas si te parece...
--- Código: Visual Basic --- dim k as long, valor as long dim Matriz(0 to (10^6) -1) as long dim o as long, p as long, q as long, r as long dim t1 as siongle, t2 as single ' cronómetros... ' asignamos valores a la matriz para empezar, no importa el valor para lo que queremos mostrar. for k= 0 to ubound(matriz) matriz(k)=k next t1= timer for k= 0 to ubound(matriz) o=matriz(k) / 3 p= matriz(k) mod 11 q= matriz(k) + 5 if matriz(k) mod 25=0 then r= matriz(k) - q else r= matriz(k) - p end if next t1= timer - t1 t2= timer for k= 0 to ubound(matriz) valor= matriz(k) o=valor / 3 p= valor mod 11 q= valor + 5 if valor mod 25=0 then r= valor - q else r= valor - p end if next t2= timer - t2 msgbox "tiempo 1: " & t1 & " tiempo 2: " & t2
Fíjate que el código es equivalente y que la segunda parte es más larga pués incluye una asignación más al principio del bucle. sin embargo correrá más rápido, porque primero investiva la dirección de la matriz 'matriz(0)' y luego necesita localizar el índice 'x' en la matriz el cálculo claramente es : dirección elemento 0 + desplazamiento indice = matriz(0) + (indice * bytes que ocupa el tipo usado).
Como en el bucle se usa matriz(k) 5 veces en cada ciclo es más lento que el 2º ejemplo que sólo utiliza 1 vez, luego recurre a una variable cuya dirección se toma sin calcular nada (*), lo que en grandes bucles o en un uso intensivo de matrices supone un buen ahorro de tiempo. Básicamente si usamos un mismo índice al menos 4 o más veces el tiempo de hacer una asignación a una variable 'nueva' compensa al uso de calcular la dirección del índice.
deaven:
Hola
M0skit0 , Nebire, muchas gracias x sus consejos.
Nebire, efectivamente el dobleteo de espacio en las matrices lo hago para reservar espacio de una sola vez, pero no mucha para no agotarla y que me permita redimensionar la menor cantidad de veces posibles.
Te comento k al principio de la elaboración del programa escogí usar colecciones, pero noté k, en el caso concreto para lo k las uso, era muchísimo más rápido utilizar matrices, x lo k en determinado momento tuve k hacer el cambio casi completo de colecciones a matrices. De hecho, en el caso concreto de mi programa, solo en un caso resultó más eficiente utilizar las colecciones k las matrices .
Como te habrás dado cuenta, soy un programador bastante novato, y no conocía los árboles k mencionas, estuve investigando un poco k erán, y te comento, k por lo k entendí, sin saberlo, actualmente ya he implementado algo un poco parecido a esos árboles.
Nebire, muchas gracias x el código, me quedó muy clara tu explicación.
Y Oigan, sinceramente les reitrero mi agradecimiento x sus comentarios y consejos. :good:
Saludos
Nebire:
--- Cita de: "deaven" ---Te comento k al principio de la elaboración del programa escogí usar colecciones, pero noté k, en el caso concreto para lo k las uso, era muchísimo más rápido utilizar matrices, x lo k en determinado momento tuve k hacer el cambio casi completo de colecciones a matrices. De hecho, en el caso concreto de mi programa, solo en un caso resultó más eficiente utilizar las colecciones k las matrices .
--- Fin de la cita ---
Deaven, si esta afirmación es cierta, es bastante probable que estés produciendo código 'espagueti'.
Un modo de determinarlo a grsosso modo es confirmar que, el hecho de que tus matrices trabajen más rápido que las colecciones no sea debido a:
a ) que sólo has considerado el tiempo de acceso a los elementos.
b ) que la operación de acceso a los elementos es sustancialmente más elevada proporcionalmente en realación a otras operaciones como añadir o eliminar elementos de la matriz.
Si es el caso a, estás producinedo código espagueti, si señalas el caso b, como, sin embargo señalabas que tienes que redimensionar miles de veces muchas matrices resulta una contradición.
Para considerar el rendimiento de una estructura no debe sólo considerarse el tiempo de acceso a los elementos, en esto una matriz es más rápido que el resto de estructuras, también debe considerarse el tiempo invertido en el resto de operaciones realizadas sobre la estructura, típicamente añadir y quitar elementos y buscar elementos determinados.
Si las matrices son los reyes en cuanto al acceso a un eleento arbitrariamente escogido no lo resulta para acceder a un determinado elemento que cumpla un criterio, por ejemplo si digo devolver el valor que sigue al que yace en el elemento x, en una matriz requiere recorer toda la matriz para buscar y verificar que el elemento hallado sea el que cumple dicho objetivo, si la matriz tiene 1 millón de elementos significa que debes recorrer 1 millón de elementos, si se emplea una estructura cuyos elementos están ordenados sólo se necesitan recorrer 20 elementos para obtener el resultado.
Igualmente añadir o quitar elementos , si a la matriz la redimensionas cada vez que añades o eliminas un elemento es lento, y no tanto si el elemento añadido o eliminado es el último que si es el primero, como según los casos no va a ser siempre el último elemento significa que si tienes 1 millón de elementos y tengo que eliminar el elemento 500.000 significa que tengo que bajar desde el elemento 500.001 hasta el final -1 una posición y luego redimensionar (aunque no estás obligado a redimensionar en un momento dado). En eso las matrices son muy lentas. Un árbol por ejemplo añade o elimina elementos en cualquier posición con mucha celeridad. Basta con conectar los hijos del nodo a eliminar (si sólo vamos a eliminar ese nodo, y no también su rama de descendencia) con el padre del nodo a eliminar, de acuerdo al tipo de árbol que sea sólo conectaremos uno de sus hijos o varios y si el árbol mantiene un tipo de orden deba seleccionarse el hijo que se conecta al padre si sólo se conecta 1...
En fin, que si estás trabajando con un programa para inteligencia artificial te recomiendo encarecidamente que diseñes varios tipos de estructuras de datos (empleando clases) para hacer un código mucho más fácil de mantener y sobretodo de ampliar reducirás drásticamente las líneas de código necesarias y globalmente correrá más rápido, incluso aunque alguna clase se base en utilizar una matriz cuando su tamaño nunca sea relativamente grande...( creo que tenía por ahí un código que me pidió mi sobrino sobre un simple colección realizada usando una matriz, la condición de uso de esa clase le sugerí que no superara como máximo los 100 elementos, si lo quieres me lo dices lo localizo y te lo expongo). A base de matrices un programa complejo se vuelve insostenible y cada vez que decidas modificarlo te dará una pereza enorme porque tendrás que 'ponerte las pilas' para entender tu propio código (qué quería hacer aquí..) y ver donde debes añadir y cómo sin afectar lo que ya está hecho...
deaven:
Hola Nebire
Te comento algunas de las particularidades de dos de las matrices k uso en el programa.
MATRIZ C
Esta matriz es la principal, tiene una vida permanente y consume casi alrededor del 90% de la memoria usada)
Esta matriz tiene 3 niveles de profundidad matricional -el formato es: C (Nivel1)(Nivel2)(Nivel3).
Si echas un vistazo a la sub RedimMat, verás k solo redimensiono los índices del Nivel1 y del Nivel3 de esa Matriz C.
Para el Nivel1, una vez creados índices extras (mandar a Redim), jamás cambiarán sus elementos (no los borraré, ni los intercambiaré, creo k esto es importante para escoger utilizar matrices en lugar de Colecciones).
Para el caso del Nivel3, una vez creados índices extras, también jamás se borrarán los elementos k contiene, pero sí se reacomodarán frecuentemente en pares, pe. si el contenido del índice 150, se colocará en el índice 100, entonces el contenido del índice 100, se colocará en el índice 150 -debido a esto, en ningún momento tengo k bajar todos los elementos k estén arriba de uno de los elementos movidos-. Creo k aquí también es preferible utilizar matrices en lugar de Colecciones.
MATRIZ CPsValores
Esta matriz es muy parecida a la matriz C (3 niveles de profundidad matricional), excepto en k consume alrededor del 50% del tiempo de proceso del CPU, se crea y se destruye constantemente.
Con esta matriz, sí k tengo grandes problemas de uso de CPU. Y pienso k es debido a k escogí erróneamente una matriz.
Debido a esa mala elección, si introduzco alrededor de 1000 páginas de conversación al programa, empiezo a tener problemas de tiempo excesivo del proceso de la información, debido a k frecuentemente tengo k eliminar algún índice del nivel1 y luego bajar un lugar a todos los índices k estén arriba del eliminado, y pues me consume muchísimo tiempo.
He pensado en algunas soluciones a ésta última situación (además de la de los árboles k me comentas) , k lamentablemente hasta la amplicación del programa podré implementar (...la novatez se paga).
Y sí, sin duda, la utilización de matrices de varias profundidades ha vuelto la depuración del programa, excesivamente tardado y complejo (ayer mismo, para hacer una sola nueva implementación k involucraba a todo el programa, me tardé toda la noche -...mmmm o será k ya estoy demasiado usado jaja :hitcomp: ,
pero...bueno, creo k el fin hará k valga la pena :rolleyes: )
Nuevamente Gracias x tus comentarios y sugerencias.
Saludos
Navegación
[*] Página Anterior
Ir a la versión completa