
/* queue.q: efficient queue data structure (Frank Drewes, May 1993) */

/* This script provides a FIFO queue data structure which implements all
   fundamental queue operations (enqueue a new element, access and dequeue
   the head element of a queue) in logarithmic time. Furthermore, normal
   forms of queues are completely determined by the queue members, so queues
   can be compared syntactically (using the stdlib::eq predicate). */

/* Queues are represented as size-balanced binary trees. Empty queues are
   denoted as nil, and the bin constructor is used to represent the interior
   nodes of the tree. The leaves of the tree are denoted with the tip
   constructor, which carries a single queue element as its argument.
   The bin symbol takes three arguments: a balance factor which is either
   0 or 1 and is used to keep the tree balanced, and the left and right
   subtree. */

public type Queue = const nil, tip X, bin B X Y;

/* enqueue Q X appends X to the queue Q */

public enqueue Q X;

enqueue nil X		= tip X;
enqueue (tip X) Y	= bin 0 (tip X) (tip Y);
enqueue (bin B X Y) Z	= bin 1 (enqueue X Z) Y if B = 0;
			= bin 0 X (enqueue Y Z) if B = 1;

/* dequeue Q removes the first element from a queue */

public dequeue Q;

dequeue (tip X)		= nil;

// the following equations *must* be in the indicated order

dequeue (bin 0 (tip X) Y)
			= Y;
dequeue (bin B X Y)	= bin 1 Y (dequeue X) if B = 0;
			= bin 0 Y (dequeue X) otherwise;

/* hd Q returns the head element of a queue */

hd (tip X)		= X;
hd (bin B X Y)		= hd X;
	
/* members converts a queue to a list */

public members Q;
	
members nil		= [];
members Q:Queue		= [hd Q | members (dequeue Q)];

/* queue converts a list to a queue */

public queue Xs;

queue Xs:List		= foldl enqueue nil Xs;
