Java Script
Java Script
Various types of dynamic storage are employed by system and applications software. For
example, a compiler frequently uses stacks to store information that is retrieved soon after it is
stored. Multiprocess computing and network management software often employs queues for
managing waiting and executing jobs (programs submitted by users).
Stack ADT
Definition: A stack is a list where insertion and deletion operations are performed only at the
head of the list.
Observation. A stack can be thought of like the spring-loaded stacks of plates in a cafeteria. You
put a plate (data object) on top of the stack, and all you can see is the top plate. When you
remove a plate from the stack, you still see the top plate only, unless the stack is empty.
Size - returns the number of objects on (currently stored in) the stack, an integer.
IsFull,IsEmpty - returns true if the stack is full (size equals some maximum constraint), or empty
(size equals zero), respectively.
Push - adds an object to the top of the stack if the stack is not full.
Pop - removes an object from the top of the stack if the stack is not empty.
Peek or Top - returns a copy of the object on top of the stack if the stack is not empty.
Example: Let a stack S begin as empty, then let us push 1 onto the stack. This is shown in Step 1
of Figure 2.4.1. Next, we push the values 2 and 3 onto the stack, as shown in Steps 2 and 3. If S
has capacity n = 3, then S is full. Popping the values off the stack as shown in Steps 4-6 yields size
= 0 (empty stack). Note how the values that were first pushed onto the stack come off the top of
the stack last. That is why the stack is called a LIFO buffer.
Figure 2.4.1. Stack operations that push a sequence (1,2,3) onto a stack, then pop it off to yield
output (3,2,1).
Implementation
A stack is usually implemented with a list, but can be implemented with an array. The list
implementation was previously described at a high level. Note that push and pop operations are
implemented at the head of the list. Additionally, the implementation should maintain a counter
for the list size that is incremented when a push operation is executed and decremented when a
pop operation is executed. A peek operation simply copies the value at the head of the list. This
can be implemented with pop, copy, and push operations.
The array implementation of a stack is more interesting, and can be faster on many different
types of machines. The array implementation has a counter called a stack pointer that denotes
the position of the array where a value was last inserted. Assuming that the array a is one-
dimensional and has indices ranging from 1 to some large value N, let the stackpointer be
denoted by j. This means that the last push() operation stored value a[j].
If another push operation is specified, then we need to perform the following steps:
1. Check to see if i = N. If so, the stack is full and we cannot execute push() and must notify
the user of stack overflow.
In contrast, if a pop operation is specified, then we need to perform the following steps:
3. Check to see if j > 0. If not, the stack is empty and we cannot execute pop() and must
notify the user of stack underflow.
5. As an optional step, store a sentinel value that indicates a null value in a[j]. This is useful
in case the stackpointer is lost, corrupted, or destroyed.
Queue ADT
Definition: A queue is a list where insertion (deletion) is performed only at the tail (head) of the
list.
Observation. A queue can be thought of like the line of customers in the bank or post office.
When a customer arrives in the queue, that person is added to back (tail) of the queue. When
the clerk calls for the next customer to be served, that person exits the queue at the front of the
queue.
IsFull,IsEmpty - returns true if the queue is full (size equals some maximum constraint), or empty
(size equals zero), respectively.
Enqueue - adds an object to the rear of the queue if the queue is not full.
Dequeue - removes an object from the front of the queue if the queue is not empty.
Example: Let a queue Q store the elements 1, 2, and 3, where 1 is at the front of the queue.
This is shown in Figure 2.4.3, Steps 1-3, below. If Q has finite capacity, then we can detect that Q
is full. Dequeueing of the values 1, 2, and 3 is shown in Figure 2.4.3, Steps 4-6, which yields an
empty queue. Note how the values that were first enqueued come out the front of the queue
first. That is why a queue implements a FIFO buffer.
Figu
re 2.4.3. Queue operations that enqueue each element of a sequence (1,2,3), then dequeue to
yield output (1,2,3).
We next examine a special type of queue, called a priority queue, which allows us to perform
special types of operations, among them sorting of values in the queue.
Special types of queues like this exist, and they are called priority queues. We discuss this
concept in detail, as follows.
Concept: A priority queue implements queue-based storage of objects, where each object is
associated with a priority value. The higher priorities indicate objects that have greater
operational importance.
Definition: A priority queue is a queue, where each element of the queue stores a tuple
containing a value x and a priority p(x) that is an integer.
Application: Priority queues are often used in scheduling applications, where a given job or
work order is assigned a priority. For example, if "1" denotes the highest priority, then one would
want to perform the highest priority jobs first (the elements of the queue where p(x) is smallest).
Figure 2.5.1. Priority queue that stores {(B,3), (A,1), (C,4), (D,2)}, where the second element of
each tuple denotes the priority, with 1 being the highest priority.
Implementation: Priority queues are usually implemented using the heap data structure
(discussed below). The heap ADT operation of MIN (or MAX) allows one to find the minimum- or
maximum-valued element stored in a heap that stores n data, in O(log n) time. Thus, if the MIN
or MAX operation acts on the priority value, then one could (in the previous discussion of
applications) retrieve the smallest priority value, which would be associated with the heap (or
priority queue) element storing a pointer to the highest-priority job.
Various instances of priority queue are used in communications (e.g., network traffic
management), operations research (e.g., assembly line optimization), and job scheduling (e.g.,
for a multiprocessor computing machine), among other applications. Thus, priority queues are of
practical importance.