
Data Structure

This illustrates a data structure, a means of storing data within a program.

You may see other such structures in the Data Structures category.
 Illustration of FIFO behavior
Task

Implement a FIFO queue.

Elements are added at one side and popped from the other in the order of insertion.



Operations:

   push   (aka enqueue)    - add element
   pop     (aka dequeue)    - pop first element
   empty                             - return truth value when empty


Errors:

   handle the error of trying to pop from an empty queue (behavior depends on the language and platform)


See

   Queue/Usage   for the built-in FIFO or queue of your language or standard library.


See also

 Array
 Associative array: Creation, Iteration
 Collections
 Compound data type
 Doubly-linked list: Definition, Element definition, Element insertion, List Traversal, Element Removal
 Linked list
 Queue: Definition, Usage
 Set
 Singly-linked list: Element definition, Element insertion, List Traversal, Element Removal
 Stack


 
MODULE Queue;
IMPORT 
	Boxes;
TYPE
	Instance* = POINTER TO LIMITED RECORD
		size: LONGINT;
		first,last: LONGINT;
		_queue: POINTER TO ARRAY OF Boxes.Box;
	END;
 
	PROCEDURE (self: Instance) Initialize(capacity: LONGINT),NEW;
	BEGIN
		self.size := 0;
		self.first := 0;
		self.last := 0;
		NEW(self._queue,capacity)
	END Initialize;
 
	PROCEDURE New*(capacity: LONGINT): Instance;
	VAR
		aQueue: Instance;
	BEGIN
		NEW(aQueue);aQueue.Initialize(capacity);RETURN aQueue
	END New;
 
	PROCEDURE (self: Instance) IsEmpty*(): BOOLEAN, NEW;
	BEGIN
		RETURN self.size = 0;
	END IsEmpty;
 
	PROCEDURE (self: Instance) Capacity*(): LONGINT, NEW;
	BEGIN
		RETURN LEN(self._queue)
	END Capacity;
 
	PROCEDURE (self: Instance) Size*(): LONGINT, NEW;
	BEGIN
		RETURN self.size
	END Size;
 
	PROCEDURE (self: Instance) IsFull*(): BOOLEAN, NEW;
	BEGIN
		RETURN self.size = self.Capacity()
	END IsFull;
 
	PROCEDURE (self: Instance) Push*(b: Boxes.Box), NEW;
	VAR
		i, j, newCapacity, oldSize: LONGINT;
		queue: POINTER TO ARRAY OF Boxes.Box;
	BEGIN
		INC(self.size);
		self._queue[self.last] := b;
		self.last := (self.last + 1) MOD self.Capacity();
		IF self.IsFull() THEN
			(* grow queue *)
			newCapacity := self.Capacity() + (self.Capacity() DIV 2);
			(* new queue *)
			NEW(queue,newCapacity);
			(* move data from old to new queue *)
			i := self.first; j := 0; oldSize := self.Capacity() - self.first + self.last;
			WHILE (j < oldSize) & (j < newCapacity - 1) DO
				queue[j] := self._queue[i];
				i := (i + 1) MOD newCapacity;INC(j)
			END;
			self._queue := queue;self.first := 0;self.last := j
		END
	END Push;
 
	PROCEDURE (self: Instance) Pop*(): Boxes.Box, NEW;
	VAR
		b: Boxes.Box;
	BEGIN
		ASSERT(~self.IsEmpty());
		DEC(self.size);
		b := self._queue[self.first];
		self._queue[self.first] := NIL;
		self.first := (self.first + 1) MOD self.Capacity();
		RETURN b
	END Pop;
 
END Queue.
 