This chapter covers stacks and queues; both are versatile data structures commonly used in the implementation of other, more complex data structures. You will learn what stacks and queues are, how and when they are used, and how to implement them. Finally, the exercises will help you to understand these concepts as well as when to apply stacks and queues to an algorithmic problem.
Stacks
In JavaScript, arrays have methods that define the stack class: pop and push (as discussed in Chapter 5). With this, a stack can be easily implemented.
Let’s first consider “peeking” at the most recently added element. This can be done simply by using the largest index of the array.
Peek
Time Complexity: O(1)
Insertion
Time Complexity: O(1)
Deletion
Time Complexity: O(1)
Access
Accessing specific elements in a data structure is important. Here, let’s take a look at how to access an element based on order.
Time Complexity: O(n)
Search will be implemented in a similar way .
Search
Time Complexity: O(n)
Queues
In JavaScript, arrays have methods that define the queue class: shift() and push() (as discussed in Chapter 5). Recall that the shift() method on an array in JavaScript removes and returns the first element of the array. Adding to a queue is commonly known as enqueuing , and removing from a queue is known as dequeuing . shift() can be used for the dequeue, and .push() can be used for the enqueue.
Peek
Insertion
Time Complexity: O(1)
Deletion
Time Complexity: O(n)
Because the shift() implementation removes the element at zero indexes and then shifts remaining indexes down consecutively, all other elements in the array need to have their indexes altered, and this takes O(n). With a linked-list implementation, as covered in Chapter 13, this can be reduced to O(1) .
Access
Time Complexity: O(n)
Search
Time Complexity: O(n)
Summary
Queue and Stack Time Complexity Summary
Access | Search | Peek | Insertion | Deletion | |
---|---|---|---|---|---|
Queue | O(n) | O(n) | O(1) | O(1) | O(n)3 |
Stack | O(n) | O(n) | O(1) | O(1) | O(1) |
Exercises
All the code for the exercises can be found on GitHub.4
DESIGN A STACK USING ONLY QUEUES AND THEN DESIGN A QUEUE USING ONLY STACKS
Stack Using Queues
A queue can be made with two stacks. A queue is a data structure that returns the first-added element with the dequeue() method. A stack is a data structure that returns the last-added element via pop. In other words, a queue removes elements in the reverse direction of a stack.
For example, examine a stack array with [1,2,3,4,5].
To reverse the order, all of the elements could be pushed onto a second stack and pop that second stack. So, the second stack array will look like this: [5,4,3,2,1].
Queue Using Stacks
DESIGN A CASHIER CLASS THAT TAKES IN A CUSTOMER OBJECT AND HANDLES FOOD ORDERING ON A FIRST-COME, FIRST-SERVED BASIS
- 1.
The cashier requires a customer name and order item for the order.
- 2.
The customer who was served first is processed first.
addOrder(customer): Enqueues a customer object to be processed by deliverOrder()
deliverOrder(): Prints the name and order for the next customer to be processed
DESIGN A PARENTHESIS VALIDATION CHECKER USING A STACK
((())) is a valid parentheses set, while ((() and ))) are not. A stack can be used to check the validity of parentheses by storing the left parenthesis and using push and triggering pop when the right parenthesis is seen.
Time Complexity: O(n)
This algorithm processes a string character by character. Hence, its time complexity is O(n), where n is the length of the string.
DESIGN A SORTABLE STACK
Time Complexity: O(n2)
This algorithm involves a reshuffling of the elements between two stacks, which in the worst possible case takes O(n2), where n is the number of elements to be sorted.