/- Copyright (c) 2019 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Selsam Simple queue implemented using two lists. Note: this is only a temporary placeholder. -/ prelude import Init.Data.Array.Basic namespace Std /-- A functional queue data structure, using two back-to-back lists. If we think of the queue as having elements pushed on the front and popped from the back, then the queue itself is effectively `eList ++ dList.reverse`. -/ structure Queue (α : Type u) where /-- The enqueue list, which stores elements that have just been pushed (with the most recently enqueued elements at the head). -/ eList : List α := [] /-- The dequeue list, which buffers elements ready to be dequeued (with the head being the next item to be yielded by `dequeue?`). -/ dList : List α := [] namespace Queue variable {α : Type u} /-- `O(1)`. The empty queue. -/ def empty : Queue α := {} instance : EmptyCollection (Queue α) := ⟨.empty⟩ instance : Inhabited (Queue α) := ⟨∅⟩ /-- `O(1)`. Is the queue empty? -/ def isEmpty (q : Queue α) : Bool := q.dList.isEmpty && q.eList.isEmpty /-- `O(1)`. Push an element on the front of the queue. -/ def enqueue (v : α) (q : Queue α) : Queue α := { q with eList := v::q.eList } /-- `O(|vs|)`. Push a list of elements `vs` on the front of the queue. -/ def enqueueAll (vs : List α) (q : Queue α) : Queue α := { q with eList := vs ++ q.eList } /-- `O(1)` amortized, `O(n)` worst case. Pop an element from the back of the queue, returning the element and the new queue. -/ def dequeue? (q : Queue α) : Option (α × Queue α) := match q.dList with | d::ds => some (d, { q with dList := ds }) | [] => match q.eList.reverse with | [] => none | d::ds => some (d, { eList := [], dList := ds }) def toArray (q : Queue α) : Array α := q.dList.toArray ++ q.eList.toArray.reverse