lean4-htt/src/Init/Data/Queue.lean
2022-09-13 03:09:25 -07:00

62 lines
1.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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.List
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