A Binary Search Tree stores distinct integers (here we enforce 0..10000
) in a binary tree so that search is fast. It obeys one rule—the BST invariant:
k
, every key in its left subtree is < k
, and every key in its right subtree is > k
. The rule holds recursively for all subtrees.It means “the element at rank k
in sorted order”, with k=1
being the smallest. We compute this by an iterative inorder walk (our baseline is O(k+h)
)—with an augmentation that stores subtree_size
at each node you can do it in O(h)
(≈O(log n)
on balanced trees).
O(log n)
.n
) if you insert sorted data. Balancing schemes (AVL, Red–Black) prevent this; we intentionally use an unbalanced BST here.Operation | Average | Worst | Notes |
---|---|---|---|
search / insert / delete | O(log n) | O(n) | Height h dominates |
min / max | O(h) | O(n) | Follow extreme left/right |
k-th smallest | O(k+h) | O(n) | With subtree sizes: O(h) |
traversals | O(n) | Visit each node once |
class Node: __slots__ = ("key","left","right") def __init__(self, key): self.key=key; self.left=None; self.right=None def search(u, x): if not u: return None if x == u.key: return u return search(u.left, x) if x < u.key else search(u.right, x) def insert(u, x): if not u: return Node(x) if x == u.key: return u if x < u.key: u.left = insert(u.left, x) else: u.right = insert(u.right, x) return u def delete(u, x): if not u: return None if x < u.key: u.left = delete(u.left, x) elif x > u.key: u.right = delete(u.right, x) else: if not u.left: return u.right if not u.right: return u.left s = u.right while s.left: s = s.left u.key = s.key u.right = delete(u.right, s.key) return u
def search_it(u, x): while u: if x == u.key: return u u = u.left if x < u.key else u.right return None def insert_it(root, x): if not root: return Node(x) p = None; u = root while u: p = u if x == u.key: return root u = u.left if x < u.key else u.right if x < p.key: p.left = Node(x) else: p.right = Node(x) return root def delete_it(root, x): p = None; u = root while u and u.key != x: p = u; u = u.left if x < u.key else u.right if not u: return root if u.left and u.right: ps = u; s = u.right while s.left: ps, s = s, s.left u.key, s.key = s.key, u.key p, u = ps, s child = u.left or u.right if not p: return child if p.left is u: p.left = child else: p.right = child return root
bisect
(library)from bisect import bisect_left class OrderedSet: def __init__(self): self.a = [] # sorted list def has(self, x): i = bisect_left(self.a, x) return i < len(self.a) and self.a[i] == x # O(log n) def insert(self, x): i = bisect_left(self.a, x) if i == len(self.a) or self.a[i] != x: self.a.insert(i, x) # O(n) shift def delete(self, x): i = bisect_left(self.a, x) if i < len(self.a) and self.a[i] == x: self.a.pop(i) # O(n) shift def kth(self, k): return self.a[k-1] # O(1)
class Node { int key; Node left, right; Node(int k){key=k;} } static Node search(Node u, int x){ if(u==null) return null; if(x==u.key) return u; return x<u.key ? search(u.left,x) : search(u.right,x); } static Node insert(Node u, int x){ if(u==null) return new Node(x); if(x==u.key) return u; if(x<u.key) u.left = insert(u.left,x); else u.right = insert(u.right,x); return u; } static Node delete(Node u, int x){ if(u==null) return null; if(x<u.key) u.left = delete(u.left,x); else if(x>u.key) u.right = delete(u.right,x); else { if(u.left==null) return u.right; if(u.right==null) return u.left; Node s=u.right; while(s.left!=null) s=s.left; u.key=s.key; u.right=delete(u.right,s.key); } return u; }
static Node searchIt(Node u, int x){ while(u!=null){ if(x==u.key) return u; u = (x<u.key)?u.left:u.right; } return null; } static Node insertIt(Node root, int x){ if(root==null) return new Node(x); Node p=null, u=root; while(u!=null){ p=u; if(x==u.key) return root; u = (x<u.key)?u.left:u.right; } if(x<p.key) p.left=new Node(x); else p.right=new Node(x); return root; } static Node deleteIt(Node root, int x){ Node p=null, u=root; while(u!=null && u.key!=x){ p=u; u=(x<u.key)?u.left:u.right; } if(u==null) return root; if(u.left!=null && u.right!=null){ Node ps=u, s=u.right; while(s.left!=null){ ps=s; s=s.left; } int tmp=u.key; u.key=s.key; s.key=tmp; p=ps; u=s; } Node child=(u.left!=null)?u.left:u.right; if(p==null) return child; if(p.left==u) p.left=child; else p.right=child; return root; }
ArrayList
+ Collections.binarySearch
(library)import java.util.*; class OrderedSet { private final ArrayList<Integer> a = new ArrayList<>(); boolean has(int x){ int i = Collections.binarySearch(a, x); return i >= 0; // O(log n) } void insert(int x){ int i = Collections.binarySearch(a, x); if(i < 0) a.add(-i-1, x); // O(n) shift } void delete(int x){ int i = Collections.binarySearch(a, x); if(i >= 0) a.remove(i); // O(n) shift } int kth(int k){ return a.get(k-1); } // O(1) }
struct Node{ int key; Node* left=nullptr; Node* right=nullptr; Node(int k):key(k){} }; Node* search(Node* u, int x){ if(!u) return nullptr; if(x==u->key) return u; return (x<u->key) ? search(u->left,x) : search(u->right,x); } Node* insert(Node* u, int x){ if(!u) return new Node(x); if(x==u->key) return u; if(x<u->key) u->left = insert(u->left,x); else u->right = insert(u->right,x); return u; } Node* deleteNode(Node* u, int x){ if(!u) return nullptr; if(x<u->key) u->left = deleteNode(u->left,x); else if(x>u->key) u->right = deleteNode(u->right,x); else{ if(!u->left){ Node* r=u->right; delete u; return r; } if(!u->right){ Node* l=u->left; delete u; return l; } Node* s=u->right; while(s->left) s=s->left; u->key=s->key; u->right=deleteNode(u->right,s->key); } return u; }
Node* searchIt(Node* u, int x){ while(u){ if(x==u->key) return u; u = (x<u->key)?u->left:u->right; } return nullptr; } Node* insertIt(Node* root, int x){ if(!root) return new Node(x); Node *p=nullptr, *u=root; while(u){ p=u; if(x==u->key) return root; u = (x<u->key)?u->left:u->right; } if(x<p->key) p->left=new Node(x); else p->right=new Node(x); return root; } Node* deleteIt(Node* root, int x){ Node *p=nullptr, *u=root; while(u && u->key!=x){ p=u; u=(x<u->key)?u->left:u->right; } if(!u) return root; if(u->left && u->right){ Node *ps=u, *s=u->right; while(s->left){ ps=s; s=s->left; } std::swap(u->key, s->key); p=ps; u=s; } Node* child = u->left ? u->left : u->right; if(!p){ delete u; return child; } if(p->left==u) p->left=child; else p->right=child; delete u; return root; }
std::vector
+ std::lower_bound
(library)#include <vector> #include <algorithm> struct OrderedSet { std::vector<int> a; bool has(int x) const { auto it = std::lower_bound(a.begin(), a.end(), x); return it != a.end() && *it == x; // O(log n) } void insert(int x){ auto it = std::lower_bound(a.begin(), a.end(), x); if(it==a.end() || *it!=x) a.insert(it, x); // O(n) shift } void erase(int x){ auto it = std::lower_bound(a.begin(), a.end(), x); if(it!=a.end() && *it==x) a.erase(it); // O(n) shift } int kth(int k) const { return a[k-1]; } // O(1) };
n-1
(e.g., sorted ascending).