Lesson 5
Practice Problems: Implementing Queues and Custom BSTs in JavaScript
Introduction to Practice Problems

Welcome to the practical segment of our JavaScript programming journey! Today, we're applying the knowledge from past lessons to solve two practice problems using advanced JavaScript data structures: queues, deques, and binary search trees with custom class keys.

First Practice Problem: Implementing Queues with Deques

Consider an event-driven system, like a restaurant. Orders arrive, and they must be handled in the order they were received, following the First In, First Out (FIFO) principle. This principle makes it a perfect scenario for a queue or deque implementation in JavaScript.

JavaScript
1class Queue { 2 constructor() { 3 // Initializing an empty queue 4 this.buffer = []; 5 } 6 7 // Adding (enqueueing) an item to the queue 8 enqueue(val) { 9 this.buffer.unshift(val); 10 } 11 12 // Removing (dequeuing) an item from the queue 13 dequeue() { 14 return this.buffer.pop(); 15 } 16 17 // Checking if the queue is empty 18 isEmpty() { 19 return this.buffer.length === 0; 20 } 21 22 // Checking the size (number of items) in the queue 23 size() { 24 return this.buffer.length; 25 } 26} 27 28// Example usage: 29const queue = new Queue(); 30queue.enqueue('order1'); 31queue.enqueue('order2'); 32console.log(queue.dequeue()); // Outputs 'order1' 33console.log(queue.isEmpty()); // Outputs false 34console.log(queue.size()); // Outputs 1

This code demonstrates the creation and operation of a Queue class, which leverages JavaScript arrays to efficiently implement a queue. The Queue class includes methods to enqueue (add) an item, dequeue (remove) an item, check if the queue is empty, and return the queue's size. Enqueue operations add an item to the beginning of the array (simulating the arrival of a new order), while dequeue operations remove an item from the end (simulating the serving of an order), maintaining the First In, First Out (FIFO) principle.

Analyzing the First Problem Solution

We've mimicked a real-world system by implementing a queue using JavaScript arrays. The enqueuing of an item taps into the FIFO principle, similar to the action of receiving a new order at the restaurant. The dequeuing serves an order, reflecting the preparation and delivery of the order.

Second Practice Problem: Using Binary Search Trees for a Leaderboard

For the second problem, envision a leaderboard for a video game. Players with their scores can be represented as objects of a custom class, then stored in a binary search tree (BST) for easy and efficient access using the @datastructures-js/binary-search-tree library.

Here is the new solution using a BST:

JavaScript
1const { BinarySearchTree } = require('@datastructures-js/binary-search-tree'); 2 3class Player { 4 constructor(name, score) { 5 this.name = name; 6 this.score = score; 7 } 8 9 // Comparator function for custom class 10 compareTo(other) { 11 if (this.score === other.score) { 12 return this.name.localeCompare(other.name); 13 } 14 return this.score - other.score; 15 } 16 17 // Defining the string representation of Player object 18 toString() { 19 return `(${this.name}, ${this.score})`; 20 } 21} 22 23class Leaderboard { 24 constructor() { 25 this.bst = new BinarySearchTree((playerA, playerB) => playerA.compareTo(playerB)); 26 } 27 28 addPlayer(player) { 29 this.bst.insert(player); 30 } 31 32 removePlayer(player) { 33 this.bst.remove(player); 34 } 35 36 getTopPlayers() { 37 const players = []; 38 this.bst.traverseInOrder((node) => players.push(node.getValue())); 39 return players; 40 } 41} 42 43// Example usage: 44const scores = new Leaderboard(); 45const player1 = new Player("John", 900); 46const player2 = new Player("Doe", 1000); 47 48scores.addPlayer(player1); 49scores.addPlayer(player2); 50 51for (const player of scores.getTopPlayers()) { 52 console.log(player.toString()); // Outputs '(John, 900)' then '(Doe, 1000)' 53}

This code snippet introduces a Player class for representing players in a video game, incorporating a custom comparator function to allow sorting by score (primary) and name (secondary). Instances of this class are then stored in a custom Leaderboard class using a binary search tree (BST) from the @datastructures-js/binary-search-tree library. The BST ensures that players are stored in sorted order based on their scores and names. This essential for functionalities like leaderboards, where players need to be ranked efficiently according to their performance.

Analyzing the Second Problem Solution

In our leaderboard system, we used a Player custom class with a comparator method for sorting. We stored instances of Player in a binary search tree (BST) with their corresponding scores. The BST allows us to access player scores in a sorted order efficiently, a common requirement in a competitive gaming system.

By practicing with these real-world examples, you'll solidify your understanding of these fundamental techniques and prepare for more advanced exercises.

Lesson Summary and Practice

We've successfully employed JavaScript’s built-in data structures — queues or deques, and binary search trees — to solve real-world problems. This hands-on approach enables us to better understand these concepts. More exercises to cement your understanding are coming up next. Happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.