2009-11-16 20 views
22

¿Cómo puedo implementar de manera eficiente una estructura de datos de listas donde puedo tener 2 vistas al principio y al final de la lista, que siempre apuntan a la cola una cola de una lista sin costosas llamadas a la inversa. es decir:Cola eficiente en Haskell

start x = [] 
end x = reverse start -- [] 
start1 = [1,2,3] ++ start 
end start1 -- [3,2,1] 

final debe ser capaz de hacer esto sin invocar 'inversa', sino simplemente mirar la lista dada desde la perspectiva de la lista de ser a la inversa automáticamente. Lo mismo debería ocurrir si creo nuevas listas de concatenaciones para comenzar.

+1

En Haskell no puede cambiar los valores. 'start' siempre será la lista vacía, y' end' siempre será 'reverse' de eso (la lista vacía). Si desea mantener el estado, debe mirar la mónada de estado. –

+1

corrección: por actualización me refiero a rebind. – TheOne

+1

@Absolute: lo que tú llamas no cambia la verdad fundamental de que no puedes * cambiar * cosas (a pesar de la mónada de IO) en Haskell. No puedes volver a unir cosas. –

Respuesta

34

siempre se puede simplemente usar Data.Sequence.

Una implementación bien conocida de una cola puramente funcional es usar dos listas. Uno para enqueue y otro para dequeue. Enqueue simplemente contraería la lista en cola. Dequeue toma el encabezado de la lista de dequeue. Cuando la lista de dequeue está vacía, vuelva a llenarla invirtiendo la lista en cola. Ver Purely Functional Datastructures. de Chris Okasaki

Aunque esta implementación usa reverse, el costo de tiempo amortizado de esto es insignificante asintóticamente. Funciona de modo que para cada enqueue, incurre en una deuda de tiempo de Θ (1) para la recarga de la lista de dequeue. El tiempo esperado de un dequeue es, por lo tanto, el doble que el de una secuencia. Este es un factor constante, por lo que el costo de ambas operaciones es Θ (1).

+14

Es insignificante * solo * si se usa efímeramente. Si su aplicación depende de la persistencia, entonces es totalmente posible encontrar ese caso O (n) cada vez que acceda a su cola. – Juliet

+4

@Juliet Con el uso de la pereza y la memorización, el límite amortizado sigue siendo O (1) mientras se mantiene la persistencia – Yuhta

+1

@Yuhta ¿puede mostrar un ejemplo utilizando la pereza y la memorización? – CMCDragonkai

1

No soy realmente un usuario de Haskell, pero encontré a blog post que dice describir una cola Haskell que puede operarse en tiempo constante amortizado. Se basa en un diseño de las excelentes estructuras de datos puramente funcionales de Chris Okasaki.

5

¿Es Data.Dequeue lo que está buscando?

(No tiene reverse pero puede agregar muy fácilmente y enviar un parche para el autor.)

+5

Conozco la biblioteca, solo quiero implementarla yo mismo como un divertido experimento mental. – TheOne

+0

O puede usar el módulo 'Data.Sequence' que ya está en la biblioteca estándar – newacct

+0

O ... pueden implementarlo como un divertido experimento mental, como establecieron lo que querían hacer. Y no hay nada malo en ello. – semicolon

Cuestiones relacionadas