Quiero usar una cola prioritaria en un problema. Creo que implementar una cola prioritaria usando una matriz es más fácil que usar un montón. ¿Qué piensas y por qué?

Hice una doble toma: en la práctica, la mayoría de los montones se implementan dentro de una matriz, por lo que no hay diferencia entre “usar una matriz y usar un montón”. Los montones son una de las muchas formas de administrar una matriz.

Quizás quiera decir “implementar una cola prioritaria como una matriz ordenada”, pero esto puede resultar en tiempos de procesamiento muy largos: la inserción de elementos en una matriz ordenada es [matemática] O (n) [/ matemática] en general, por lo que procesar n elementos puede ser tan malo como [matemáticas] O (n ^ 2) [/ matemáticas]. A menos que sepa que n será realmente pequeño, esto podría matar su algoritmo, ya que procesar la misma cantidad de elementos en un montón es [math] O (n log n) [/ math].

Honestamente, los algoritmos de almacenamiento dinámico ni siquiera son tan difíciles de implementar: la inserción, el pop y el almacenamiento dinámico solo deben ser unas pocas docenas de líneas de código. Y si está en C ++, ya se han escrito para usted: std :: make_heap, std :: push_heap y std :: pop_heap son parte de la biblioteca estándar. Aunque realmente, si tiene la biblioteca estándar, simplemente debe usar std :: priority_queue y terminar con ella.

Por cierto, la respuesta de Adrian Ho sobre “un número relativamente pequeño de prioridades” es absolutamente correcta si realmente tiene un número relativamente pequeño de prioridades. Y, en general, es muy común que su algoritmo particular tenga propiedades útiles que pueden explotarse para hacer que el código sea más simple y más eficiente. Mantenerse atento a tales propiedades es parte de ser un desarrollador eficaz. Sin embargo, si tiene una gran cantidad de prioridades, una gran cantidad de elementos, y necesita la capacidad de agregar nuevos elementos sobre la marcha antes de que se hayan consumido todos los actuales, lo que está buscando es una cola prioritaria. En ese caso, ser un desarrollador eficaz significa utilizar la función de cola de prioridad existente de su idioma, porque rara vez es una buena idea reinventar estructuras de datos comunes.

Quiero usar una cola prioritaria en un problema. Creo que implementar una cola prioritaria usando una matriz es más fácil que usar un montón. ¿Qué piensas y por qué?

Creo que puedes hacerlo mejor una vez que dejas de pensar de manera tan abstracta.

En la vida real, la mayoría de las colas de prioridad solo se extienden sobre un puñado de valores de prioridad reales, que generalmente son (o se pueden asignar fácilmente) a un rango de enteros [matemática] [0..k) [/ matemática]. Estoy bastante seguro de que cualquiera de los desarrolladores de software a los que he asesorado a lo largo de los años respondería instantáneamente a esta descripción con:

¡Oh, solo use una matriz de colas, donde el índice de la matriz es la prioridad!

La complejidad del tiempo es extremadamente favorable. Las operaciones Insert / delete / isEmpty en las colas individuales son [math] \ Theta (1) [/ math], a menos que esté haciendo algo realmente extraño, y la selección de la cola por prioridad (básicamente “que es el primer no vacío queue? ”) es [math] \ Theta (k) [/ math], para una complejidad general get_next_item de [math] \ Theta (k) [/ math], donde [math] k [/ math] es bastante pequeño.

Más importante aún, la complejidad de la implementación es sustancialmente menor que con una sola matriz o un montón, si tiene que implementar todo desde cero. Una cola de búfer circular o lista enlazada es mucho más fácil de obtener que un montón.

¡Buena suerte!

Implementar una cola prioritaria utilizando una matriz de una manera ingenua es definitivamente más fácil de implementar que un montón, pero se ejecutará mucho más lentamente si sus matrices son muy grandes.

Supongamos que implementa una matriz de una manera ingenua.

Cada operación push () tomará tiempo [matemático] \ Theta (1) [/ matemático] (amortizado), pero cada pop () tomará tiempo [matemático] \ Theta (n) [/ matemático], donde n es el tamaño de la cola de prioridad. Esto es porque tienes que encontrar el máximo y luego cambiar todo.

Ahora, supongamos que usa un montón. Cada push () y pop () toman tiempo [math] \ Theta (\ log n) [/ math]. Ahora, digamos [matemáticas] n = 1024 [/ matemáticas]. Luego, un algoritmo [matemático] \ Theta (n) [/ matemático] tomará aproximadamente 1024 operaciones, mientras que un [matemático] \ Theta (\ log n) [/ matemático] tomará solo 10 operaciones.