Data Structures

Data structures are fundamental building blocks for organizing and storing data in a way that allows for efficient access and modification. Understanding different data structures is crucial for writing performant and scalable software.

Common Data Structures

Arrays

Arrays are ordered collections of elements, accessed by an index. They provide fast access to elements if the index is known.

Example:
let numbers = [10, 20, 30, 40, 50];
console.log(numbers[0]); // Output: 10
console.log(numbers.length); // Output: 5
numbers.push(60); // Add an element to the end
console.log(numbers); // Output: [10, 20, 30, 40, 50, 60]
            

Linked Lists

Linked lists are linear data structures where elements are not stored contiguously. Each element (node) contains data and a reference (pointer) to the next node in the sequence.

Example (Conceptual):
// Conceptual representation
// Node structure: { data: value, next: pointer }
// List: Node1 -> Node2 -> Node3 -> null
let head = { data: 'Apple', next: null };
let secondNode = { data: 'Banana', next: null };
head.next = secondNode;
// ... and so on
            

Stacks

Stacks are linear data structures that follow the Last-In, First-Out (LIFO) principle. Elements are added (pushed) and removed (popped) from the same end, called the top.

Example:
let stack = [];
stack.push('A'); // stack: ['A']
stack.push('B'); // stack: ['A', 'B']
console.log(stack.pop()); // Output: 'B', stack: ['A']
console.log(stack.peek()); // Output: 'A' (if peek is implemented)
            

Queues

Queues are linear data structures that follow the First-In, First-Out (FIFO) principle. Elements are added at one end (rear) and removed from the other end (front).

Example:
let queue = [];
queue.push('Task 1'); // enqueue: queue: ['Task 1']
queue.push('Task 2'); // enqueue: queue: ['Task 1', 'Task 2']
console.log(queue.shift()); // dequeue: Output: 'Task 1', queue: ['Task 2']
            

Hash Tables (Maps/Dictionaries)

Hash tables store key-value pairs. They use a hash function to compute an index into an array of buckets or slots, from which the desired value can be found.

Example:
let user = {
    id: 101,
    name: "Alice",
    email: "alice@example.com"
};
console.log(user.name); // Output: Alice
console.log(user['email']); // Output: alice@example.com

let userMap = new Map();
userMap.set('id', 101);
userMap.set('name', 'Alice');
console.log(userMap.get('name')); // Output: Alice
            

Trees

Trees are hierarchical data structures consisting of nodes connected by edges. They typically have a root node, and each node can have zero or more child nodes.

Example (Binary Tree Node):
class TreeNode {
    constructor(value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

let root = new TreeNode(50);
root.left = new TreeNode(30);
root.right = new TreeNode(70);
root.left.left = new TreeNode(20);
root.left.right = new TreeNode(40);
            

Graphs

Graphs are non-linear data structures composed of nodes (vertices) connected by edges. They are used to represent relationships between objects.

Example (Adjacency List Representation):
// Represents a graph with vertices A, B, C, D
// A is connected to B and C
// B is connected to A and D
// C is connected to A
// D is connected to B
let graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D'],
    'C': ['A'],
    'D': ['B']
};
            

Choosing the Right Data Structure

The choice of data structure depends heavily on the specific problem requirements:

Understanding the time and space complexity of operations for each data structure is essential for optimizing algorithm performance.