Skip to main content

Binary Search Tree

A Binary Search Tree (BST) is a hierarchical data structure where each node has at most two children, with all left descendants less than the current node and all right descendants greater than the current node.

Structureโ€‹

class Node {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}

class BinarySearchTree {
constructor() {
this.root = null;
}
}

Advantagesโ€‹

  • Efficient searching (O(log n) on average)
  • Maintains sorted order
  • Flexible size
  • Supports many operations efficiently

Disadvantagesโ€‹

  • Can become unbalanced
  • No constant-time operations
  • More complex than arrays for simple operations
  • Not cache-friendly due to non-contiguous memory storage

Common Operationsโ€‹

  1. Insert - Add a new value
  2. Search - Find a value
  3. Delete - Remove a value
  4. Traversal - Visit all nodes
    • In-order (Left, Root, Right)
    • Pre-order (Root, Left, Right)
    • Post-order (Left, Right, Root)

Time Complexitiesโ€‹

OperationAverageWorst
AccessO(log n)O(n)
SearchO(log n)O(n)
InsertionO(log n)O(n)
DeletionO(log n)O(n)

Implementation Exampleโ€‹

Here's a complete implementation of a Binary Search Tree with common operations:

class Node {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}

class BinarySearchTree {
constructor() {
this.root = null;
}

// Insert a new value
insert(value) {
const newNode = new Node(value);

if (!this.root) {
this.root = newNode;
return this;
}

let current = this.root;
while (true) {
if (value === current.value) return undefined;
if (value < current.value) {
if (!current.left) {
current.left = newNode;
return this;
}
current = current.left;
} else {
if (!current.right) {
current.right = newNode;
return this;
}
current = current.right;
}
}
}

// Find a value
find(value) {
if (!this.root) return false;

let current = this.root;
while (current) {
if (value === current.value) return true;
if (value < current.value) {
current = current.left;
} else {
current = current.right;
}
}
return false;
}

// In-order traversal
inOrder() {
const data = [];

function traverse(node) {
if (node.left) traverse(node.left);
data.push(node.value);
if (node.right) traverse(node.right);
}

if (this.root) traverse(this.root);
return data;
}

// Pre-order traversal
preOrder() {
const data = [];

function traverse(node) {
data.push(node.value);
if (node.left) traverse(node.left);
if (node.right) traverse(node.right);
}

if (this.root) traverse(this.root);
return data;
}

// Post-order traversal
postOrder() {
const data = [];

function traverse(node) {
if (node.left) traverse(node.left);
if (node.right) traverse(node.right);
data.push(node.value);
}

if (this.root) traverse(this.root);
return data;
}
}

Visual Representationโ€‹

A binary search tree can be visualized as a hierarchical structure:

       8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13

Common Use Casesโ€‹

  1. Database Indexing

    • Efficient data retrieval
    • Range queries
  2. File Systems

    • Directory structures
    • File organization
  3. Applications

    • Expression parsers
    • Priority queues
    • Spell checkers

Practice Problemsโ€‹

To master binary search trees, try solving these common problems:

  1. Check if a binary tree is a valid BST
  2. Find the kth smallest element
  3. Convert sorted array to BST
  4. Find lowest common ancestor
  5. Balance an unbalanced BST
  6. Find closest value in BST

Additional Resourcesโ€‹

Comparison with Other Data Structuresโ€‹

BST vs Arrayโ€‹

BST Advantages:

  • Better search time (O(log n) vs O(n))
  • Dynamic size
  • Efficient insertion/deletion

Array Advantages:

  • Cache-friendly
  • Constant-time access
  • Simpler implementation

BST vs Hash Tableโ€‹

BST Advantages:

  • Ordered data
  • Range queries
  • No collision handling needed

Hash Table Advantages:

  • O(1) average operations
  • Simpler implementation
  • Better space efficiency