Mejora del rendimiento para el algoritmo de búsqueda de primera categoría -- javascript campo con algorithm camp codereview Relacionados El problema

Improving performance for Depth-first search algorithm


2
vote

problema

Español

Estoy usando el siguiente algoritmo de búsqueda de profundidad: calcular el valor de una propiedad llamada /** * file queue.c * * rief A double-ended queue (deque). Elements can be added or removed from * either the front or the back side. * warning The current implementation is NOT interrupt safe. Make sure interrupts * are disabled before access the QUEUE otherwise the program might yield * unexpected results. */ #include "queue.h" #include <stdbool.h> /** * Initializes - resets the queue. */ void queue_init(struct queue * queue) { memset(queue->data, 0, queue->size); queue->back_idx = 0; queue->front_idx = 0; queue->elements = 0; } /** * Checks if queue is full. * * eturns true if queue is full. */ bool queue_is_full(struct queue * queue) { return (queue->elements == queue->size); } /** * Checks if queue is empty * * eturns true if queue is empty. */ bool queue_is_empty(struct queue * queue) { return (queue->elements == 0); } /** * Adds one byte to the front of the queue. * * eturns false if the queue is full. */ bool queue_add_front(struct queue * queue, QueueDataType_t data) { if (queue_is_full(queue)) { return 0; } if (queue_is_empty(queue) == 0) { queue->front_idx = (queue->front_idx + 1) >= queue->size ? 0 : (queue->front_idx + 1); } queue->data[queue->front_idx] = data; queue->elements++; return 1; } /** * Adds one byte to the back of the queue. * * eturns false if the queue is full. */ bool queue_add_back(struct queue * queue, QueueDataType_t data) { if (queue_is_full(queue)) { return 0; } if (queue_is_empty(queue) == 0) { queue->back_idx = (queue->back_idx == 0) ? (queue->size - 1) : (queue->back_idx - 1); } queue->data[queue->back_idx] = data; queue->elements++; return 1; } /** * Reads one byte from the front of the queue. * * eturns false if the queue is empty. */ bool queue_get_front(struct queue * queue, QueueDataType_t * data) { if (queue_is_empty(queue)) { return 0; } *data = queue->data[queue->front_idx]; queue->front_idx = (queue->front_idx == 0) ? (queue->size - 1) : (queue->front_idx - 1); queue->elements--; return 1; } /** * Reads one byte from the back of the queue. * * eturns false if the queue is empty. */ bool queue_get_back(struct queue * queue, QueueDataType_t * data) { if (queue_is_empty(queue)) { return 0; } *data = queue->data[queue->back_idx]; queue->back_idx = (queue->back_idx + 1) >= queue->size ? 0 : (queue->back_idx + 1); queue->elements--; return 1; } 0 basado en valores anteriores de /** * file queue.c * * rief A double-ended queue (deque). Elements can be added or removed from * either the front or the back side. * warning The current implementation is NOT interrupt safe. Make sure interrupts * are disabled before access the QUEUE otherwise the program might yield * unexpected results. */ #include "queue.h" #include <stdbool.h> /** * Initializes - resets the queue. */ void queue_init(struct queue * queue) { memset(queue->data, 0, queue->size); queue->back_idx = 0; queue->front_idx = 0; queue->elements = 0; } /** * Checks if queue is full. * * eturns true if queue is full. */ bool queue_is_full(struct queue * queue) { return (queue->elements == queue->size); } /** * Checks if queue is empty * * eturns true if queue is empty. */ bool queue_is_empty(struct queue * queue) { return (queue->elements == 0); } /** * Adds one byte to the front of the queue. * * eturns false if the queue is full. */ bool queue_add_front(struct queue * queue, QueueDataType_t data) { if (queue_is_full(queue)) { return 0; } if (queue_is_empty(queue) == 0) { queue->front_idx = (queue->front_idx + 1) >= queue->size ? 0 : (queue->front_idx + 1); } queue->data[queue->front_idx] = data; queue->elements++; return 1; } /** * Adds one byte to the back of the queue. * * eturns false if the queue is full. */ bool queue_add_back(struct queue * queue, QueueDataType_t data) { if (queue_is_full(queue)) { return 0; } if (queue_is_empty(queue) == 0) { queue->back_idx = (queue->back_idx == 0) ? (queue->size - 1) : (queue->back_idx - 1); } queue->data[queue->back_idx] = data; queue->elements++; return 1; } /** * Reads one byte from the front of the queue. * * eturns false if the queue is empty. */ bool queue_get_front(struct queue * queue, QueueDataType_t * data) { if (queue_is_empty(queue)) { return 0; } *data = queue->data[queue->front_idx]; queue->front_idx = (queue->front_idx == 0) ? (queue->size - 1) : (queue->front_idx - 1); queue->elements--; return 1; } /** * Reads one byte from the back of the queue. * * eturns false if the queue is empty. */ bool queue_get_back(struct queue * queue, QueueDataType_t * data) { if (queue_is_empty(queue)) { return 0; } *data = queue->data[queue->back_idx]; queue->back_idx = (queue->back_idx + 1) >= queue->size ? 0 : (queue->back_idx + 1); queue->elements--; return 1; } 1 de los elementos de los padres recursivamente.

El resultado del script es correcto (consola abierta para ver el resultado), pero me gustaría su revisión de código con respecto al rendimiento, considerando que 99887766555443312 podría contenía miles de objetos ... ¿Cómo podría más? mejorar mi código?

Notas: Estoy apuntando a las últimas versiones de Chrome y Firefox.

  /**  * file queue.c  *  * rief   A double-ended queue (deque). Elements can be added or removed from  *          either the front or the back side.  * warning The current implementation is NOT interrupt safe. Make sure interrupts  *          are disabled before access the QUEUE otherwise the program might yield  *          unexpected results. */  #include "queue.h" #include <stdbool.h>   /**  * Initializes - resets the queue. */ void queue_init(struct queue * queue) {     memset(queue->data, 0, queue->size);     queue->back_idx = 0;     queue->front_idx = 0;     queue->elements = 0; }  /**  * Checks if queue is full.  *   *  eturns true if queue is full. */ bool queue_is_full(struct queue * queue) {     return (queue->elements == queue->size); }  /**  * Checks if queue is empty  *   *  eturns true if queue is empty. */ bool queue_is_empty(struct queue * queue) {     return (queue->elements == 0); }  /**  * Adds one byte to the front of the queue.   *   *  eturns false if the queue is full.  */ bool queue_add_front(struct queue * queue,                       QueueDataType_t data) {     if (queue_is_full(queue))     {         return 0;     }      if (queue_is_empty(queue) == 0)     {         queue->front_idx = (queue->front_idx + 1) >= queue->size ? 0 : (queue->front_idx + 1);     }      queue->data[queue->front_idx] = data;         queue->elements++;     return 1; }  /**  * Adds one byte to the back of the queue.  *   *  eturns false if the queue is full.  */ bool queue_add_back(struct queue * queue,                      QueueDataType_t data) {     if (queue_is_full(queue))     {         return 0;     }      if (queue_is_empty(queue) == 0)     {         queue->back_idx = (queue->back_idx == 0) ? (queue->size - 1) : (queue->back_idx - 1);     }      queue->data[queue->back_idx] = data;     queue->elements++;     return 1;     }  /**  * Reads one byte from the front of the queue.  *   *  eturns false if the queue is empty. */ bool queue_get_front(struct queue * queue,                       QueueDataType_t * data) {     if (queue_is_empty(queue))     {         return 0;     }          *data = queue->data[queue->front_idx];     queue->front_idx = (queue->front_idx == 0) ? (queue->size - 1) : (queue->front_idx - 1);     queue->elements--;     return 1; }  /**  * Reads one byte from the back of the queue.  *   *  eturns false if the queue is empty. */ bool queue_get_back(struct queue * queue,                      QueueDataType_t * data) {     if (queue_is_empty(queue))     {         return 0;     }      *data = queue->data[queue->back_idx];     queue->back_idx = (queue->back_idx + 1) >= queue->size ? 0 : (queue->back_idx + 1);     queue->elements--;     return 1; } 3  
Original en ingles

I am using the following Depth-first search algorithm to compute value of a property called rotation_absolute based on previous values of rotation of parent elements recursively.

The result of the script is correct (open console to see the result) but I would like your code review regarding performance, considering that app.data could contained thousands of objects... how could I further improve my code?

Notes: I am targeting latest versions of Chrome and FireFox.

     var app = {             getById: function (id) {                 var result;                 this.data.some(function (item) {                     if (item.id === id) {                         result = item;                         return true;                     } else {                         return false;                     }                 });                 return result;             },             findChildren: function (id) {                 var result = this.data.filter(function (item) {                     if (item.parent === id) {                         return true;                     } else {                         return false;                     }                 });                 return result;             },             data: [                 {                     id: 'root',                     parent: '',                     rotation: 0,                     rotation_absolute: 0                 },                 {                     id: 'a',                     parent: 'root',                     rotation: 10                 },                     {                         id: 'a-a',                         parent: 'a',                         rotation: 10                     },                     {                         id: 'a-b',                         parent: 'a',                         rotation: 10                     },                         {                             id: 'a-b-a',                             parent: 'a-b',                             rotation: 10                         },                             {                                 id: 'a-b-a-a',                                 parent: 'a-b-a',                                 rotation: 10                             },                                 {                                     id: 'a-b-a-a-a',                                     parent: 'a-b-a-a',                                     rotation: 10                                 },                             {                                 id: 'a-b-a-b',                                 parent: 'a-b-a',                                 rotation: 10                             },                 {                     id: 'b',                     parent: 'root',                     rotation: 0                 },                     {                         id: 'b-a',                         parent: 'b',                         rotation: 10                     },                         {                             id: 'b-a-a',                             parent: 'b-a',                             rotation: 10                         },                             {                                 id: 'b-a-a-a',                                 parent: 'b-a-a',                                 rotation: 10                             },                     {                         id: 'b-b',                         parent: 'b',                         rotation: 10                     },             ],             calculate: function () {                 var recursion = function (id) {                     var children = this.findChildren(id);                     var parent = this.getById(id);                     children.forEach(function (item) {                         if ('rotation_absolute' in item === false) {                             item.rotation_absolute = 0;                         }                         item.rotation_absolute += item.rotation + parent.rotation_absolute;                         recursion.call(this, item.id)                     }, this);                 };                  recursion.call(this, 'root')             },         };         app.calculate();         console.clear();         console.log(JSON.stringify(app.data));
     
 
 

Lista de respuestas

2
 
vote
vote
La mejor respuesta
 
              this.data.some(function (item) {                 if (item.id === id) {                     result = item;                     return true;                 } else {                     return false;                 }             });   

Encuentro tales construcciones extrañas, algo sobre return true else return false siempre me molesta. En este caso, no hay mucho que pueda hacer al respecto, lo mejor que pueda hacer es usar un más implícito eliminando el lo demás:

              this.data.some(function (item) {                 if (item.id === id) {                     result = item;                     return true;                 }                 return false;             });   

              var result = this.data.filter(function (item) {                 if (item.parent === id) {                     return true;                 } else {                     return false;                 }             });   

Aquí, sin embargo, no hay razón para tener esta construcción.

Solo puedes devolver las comparaciones booleanas, así:

              var result = this.data.filter(function (item) {                 return item.parent === id;             });   

Para el calculate Función ... Bueno, si podría reestructurar sus datos, eso sería agradable. En este momento, se refiere a cada elemento por id , lo que significa que necesita ID únicos en toda la lista.

Dependiendo de cómo funciona los elementos de acceso de la lista, tiene $ O (1) $ para recuperar un elemento o $ O (n / 2) $. Es decir, ya sea que pueda usar la ID para decir "Oh, ese número 35 de entrada, permítame ver, una página de memoria se ajusta a 24 artículos, así que tendría que mirar la página 2, entrada 11 ... ¡Ahí está! " Considerando que si no tiene tal traducción, está atrapado con comprobar cada artículo.

Para 13 artículos, no importa. Para 100 artículos, lo hace. 100 artículos accedidos a través de acceso directo significa que tiene 100 recuperaciones, 100 artículos a través de la búsqueda lineal significa que tiene 5050 recuperaciones (1 + 2 + 3 + 4 ... + 100). Busque "números triangulares" si desea ver lo mal que se pone.

Para solucionar esto, podrías hacer una de las dos cosas:

  1. Hazlo para que la identificación dé acceso directo. Esto se podría hacer con funciones o matrices de hash o ... Buscar estructuras de datos con $ O (1) $ Acceso.

  2. Hazlo para que el espacio de búsqueda sea más pequeño. Por ejemplo, en lugar de vincular los nodos juntos por ID, nido a los nodos a través de proporcionar un atributo 998877666555443337 que contiene más nodos. Luego, solo tiene que buscar en un sublista, lo que significa que estaría buscando en listas en cualquier lugar del 1 al 20% de su lista principal. Dada la forma en que la escala de iteraciones de acceso, 5 * 20 es solo 1050 iteraciones, en comparación con los 5050 que tuvimos anteriormente.

 
            this.data.some(function (item) {                 if (item.id === id) {                     result = item;                     return true;                 } else {                     return false;                 }             }); 

I find such constructions weird, something about return true else return false always bothers me. In this case, there's not much you can do about it, best you could probably do is use an implicit else by removing the else:

            this.data.some(function (item) {                 if (item.id === id) {                     result = item;                     return true;                 }                 return false;             }); 

            var result = this.data.filter(function (item) {                 if (item.parent === id) {                     return true;                 } else {                     return false;                 }             }); 

Here, however, there's no reason to have this construction.

You can just return boolean comparisons like so:

            var result = this.data.filter(function (item) {                 return item.parent === id;             }); 

For the calculate function... well, if you could restructure your data, that'd be nice. Right now you refer to each element by id, which means that you need unique ids throughout the entire list.

Depending on how accessing elements of the list works, you either have \$O(1)\$ for retrieving an element or \$O(n/2)\$. That is, either you can use the id to say "oh, that's entry number 35, let me see, one memory page fits 24 items, so I'd have to look at page 2, entry 11... there it is!" Whereas if you don't have such a translation ready, you're stuck with checking each item.

For 13 items, it does not matter. For 100 items, it does. 100 items accessed via direct access means you have 100 retrievals, 100 items accessed via linear search means you have 5050 retrievals (1+2+3+4...+100). Look up "triangular numbers" if you wanna see how bad it gets.

To fix this, you could do one of two things:

  1. Make it so that the id gives direct access. This could be done with hash functions or arrays or... look up data structures with \$O(1)\$ access.

  2. Make it so that the search space is smaller. For instance, instead of linking nodes together by ID, nest nodes via providing a children attribute containing more nodes. Then you only have to search in a sublist, meaning that you'd be searching in lists anywhere from 1 to 20% of your main list. Given the way access iterations scale, 5*20 is only 1050 iterations, compared to the 5050 we had earlier.

 
 
   
   

Relacionados problema

5  Proyecto EULER NO. 17: contando letras para escribir los números de 1 a 1000  ( Project euler no 17 counting letters to write the numbers from 1 to 1000 ) 
Soy muy nuevo en la programación y, cierto, estoy avergonzado de compartir mi código para la crítica. Este código funciona y produce la respuesta correcta a l...

25  Algoritmo para transformar una palabra a otra a través de palabras válidas  ( Algorithm to transform one word to another through valid words ) 
He estado practicando retroceso y quería saber cómo puedo mejorar mi código. Por ejemplo, no quiero usarlo global. Además, no estoy seguro de si mi código fun...

8  Simple GCD Utility en Java  ( Simple gcd utility in java ) 
i anteriormente discutido El rendimiento se refiere a diferentes algoritmos GCD. Escribí una simple clase de Java que implementa el algoritmo binario GCD. E...

6  Encontrar el siguiente palíndromo de una cadena de números  ( Finding the next palindrome of a number string ) 
Aquí está el problema: Un entero positivo se llama palíndromo si su representación en el El sistema decimal es el mismo cuando se lee de izquierda a dere...

2  Dos formas de aleatorias aleatoriamente las tarjetas  ( Two ways to randomly shuffle cards ) 
Aquí hay dos implementaciones que escribí para aleatorizar las tarjetas. El primer método ( dt5 ) Selecciona una tarjeta aleatoria, luego lo quita al frent...

35  Demasiados bucles en la aplicación de dibujo  ( Too many loops in drawing app ) 
Tengo un método que tiene muchos bucles: #ifndef __RUNES_STRUCTURES_H #define __RUNES_STRUCTURES_H /* Runes structures. */ struct Game { char board[2...

5  Orden de número más grande en cadena  ( Largest number order in string ) 
Dada una cadena, suponiendo que la cadena sea solo números, reorganice la cadena a la que sea el mayor número posible. a continuación es mi solución al pr...

1  Retire todos los nodos que no se encuentren en ningún camino con suma> = k  ( Remove all nodes which dont lie in any path with sum k ) 
Dado un árbol binario, una ruta completa se define como un camino desde la raíz a una hoja. La suma de todos los nodos en ese camino se define como la suma d...

56  Proyecto Euler Problema 1 en Python - Múltiples de 3 y 5  ( Project euler problem 1 in python multiples of 3 and 5 ) 
Me gustaría sugerencias para optimizar esta solución de fuerza bruta a problema 1 . El algoritmo actualmente comprueba cada entero entre 3 y 1000. Me gustarí...

1  Compruebe si dos cadenas son permutación entre sí  ( Check if two strings are permutation of each other ) 
private String sort(String word) { char[] content = word.toCharArray(); Arrays.sort(content); return new String(content); } private boolea...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos