二叉搜索樹(Binary Search Tree, BST)是資料結構中最基礎且重要的動態查找結構,也是 AVL 樹、紅黑樹、Treap 等平衡樹的基石。本文提供完整的 C++ 模板實現,涵蓋節點設計、核心操作(查找最值、包含判斷、插入、刪除、遍歷、清空)、遞歸與迭代兩種實現風格、刪除操作的三種情況詳細圖解,並附帶記憶體管理最佳實踐。
template <typename T>
struct BinaryNode {
T element;
BinaryNode* left;
BinaryNode* right;
BinaryNode(const T& e, BinaryNode* l = nullptr, BinaryNode* r = nullptr)
: element(e), left(l), right(r) {}
};
template <typename T>
class BinarySearchTree {
public:
BinarySearchTree() : root(nullptr) {}
~BinarySearchTree() { makeEmpty(); }
// 公有介面
const T& findMin() const;
const T& findMax() const;
bool contains(const T& x) const;
bool isEmpty() const { return root == nullptr; }
void printTree() const; // 中序遍歷輸出
void insert(const T& x);
void remove(const T& x);
void makeEmpty();
private:
BinaryNode<T>* root;
// 私有遞歸輔助函數
void insert(const T& x, BinaryNode<T>*& t) const;
void remove(const T& x, BinaryNode<T>*& t) const;
BinaryNode<T>* findMin(BinaryNode<T>* t) const;
BinaryNode<T>* findMax(BinaryNode<T>* t) const;
bool contains(const T& x, BinaryNode<T>* t) const;
void printTree(BinaryNode<T>* t) const;
void makeEmpty(BinaryNode<T>*& t) const;
};

利用 BST 性質:最小值在最左葉節點,最大值在最右葉節點。
// 遞歸版 findMin
template <typename T>
BinaryNode<T>* BinarySearchTree<T>::findMin(BinaryNode<T>* t) const {
if (t == nullptr) return nullptr;
if (t->left == nullptr) return t;
return findMin(t->left);
}
// 迭代版 findMax(面試常考非遞歸寫法)
template <typename T>
BinaryNode<T>* BinarySearchTree<T>::findMax(BinaryNode<T>* t) const {
if (t == nullptr) return nullptr;
while (t->right != nullptr) t = t->right;
return t;
}
// 公有介面
template <typename T>
const T& BinarySearchTree<T>::findMin() const {
if (isEmpty()) throw runtime_error("Tree is empty");
return findMin(root)->element;
}
template <typename T>
bool BinarySearchTree<T>::contains(const T& x, BinaryNode<T>* t) const {
if (t == nullptr) return false;
if (x < t->element) return contains(x, t->left);
if (x > t->element) return contains(x, t->right);
return true; // 找到
}
template <typename T>
void BinarySearchTree<T>::insert(const T& x, BinaryNode<T>*& t) const {
if (t == nullptr) {
t = new BinaryNode<T>(x, nullptr, nullptr);
} else if (x < t->element) {
insert(x, t->left);
} else if (x > t->element) {
insert(x, t->right);
}
// 相等不處理(忽略重複)
}
刪除節點 t 需分三種情況處理(參考下圖):

delete,父節點對應指標置 nullptrtemplate <typename T>
void BinarySearchTree<T>::remove(const T& x, BinaryNode<T>*& t) const {
if (t == nullptr) return; // 未找到
if (x < t->element) {
remove(x, t->left);
} else if (x > t->element) {
remove(x, t->right);
} else { // 找到目標節點 t
if (t->left != nullptr && t->right != nullptr) { // 情況 3:雙子節點
t->element = findMin(t->right)->element; // 用右子樹最小值替換
remove(t->element, t->right); // 刪除右子樹中該最小值節點
} else { // 情況 1 或 2:至多一個子節點
BinaryNode<T>* old = t;
t = (t->left != nullptr) ? t->left : t->right; // 子節點頂替
delete old;
}
}
}
template <typename T>
void BinarySearchTree<T>::printTree(BinaryNode<T>* t) const {
if (t != nullptr) {
printTree(t->left);
cout << t->element << " ";
printTree(t->right);
}
}
template <typename T>
void BinarySearchTree<T>::makeEmpty(BinaryNode<T>*& t) const {
if (t != nullptr) {
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
t = nullptr;
}
}
#include <iostream>
#include <stdexcept>
using namespace std;
// ... 上述 BinarySearchTree 完整實現 ...
int main() {
BinarySearchTree<int> bst;
// 插入測試
vector<int> data = {50, 30, 70, 20, 40, 60, 80, 10, 25, 35, 45};
for (int v : data) bst.insert(v);
cout << "中序遍歷 (有序): ";
bst.printTree(); // 10 20 25 30 35 40 45 50 60 70 80
cout << endl;
cout << "最小值: " << bst.findMin() << endl; // 10
cout << "最大值: " << bst.findMax() << endl; // 80
cout << "包含 35: " << bst.contains(35) << endl; // 1
cout << "包含 99: " << bst.contains(99) << endl; // 0
// 刪除測試
bst.remove(20); // 葉節點
bst.remove(30); // 單子節點 (左子 25)
bst.remove(50); // 雙子節點 (根節點)
cout << "刪除 20,30,50 後: ";
bst.printTree(); // 10 25 35 40 45 60 70 80
cout << endl;
return 0;
}
| 操作 | 平均情況 | 最壞情況 | 空間複雜度 |
|---|---|---|---|
| 查找/插入/刪除 | O(log n) | O(n) (退化為鏈表) | O(h) 遞歸棧 / O(1) 迭代 |
| 遍歷 | O(n) | O(n) | O(h) |
| 查找最值 | O(log n) | O(n) | O(h) / O(1) |
h 為樹高。平衡時 h ≈ log₂n,極端有序插入退化為鏈表 h = n。
template <typename T>
struct Node {
T element;
unique_ptr<Node> left, right;
Node(const T& e) : element(e) {}
};
// 遞歸函數改用 unique_ptr& 參數,無需手動 delete
// 實現 begin()/end() 返回 inorder_iterator
// 支援 range-based for: for (auto v : bst) cout << v;
int count; 节點存儲重複次數BST 非自平衡,實際工程請使用:
min < node < maxsize 域 O(log n)二叉搜索樹以其優雅的遞歸結構、O(log n) 平均效能、簡單直觀的實現,成為資料結構教學與工程基礎的核心。本文提供的完整模板實現涵蓋所有核心操作,重點闡述了刪除操作的三種情況處理邏輯與遞歸/迭代雙實現風格。理解 BST 是通往 AVL、紅黑樹、B+ 樹等進階平衡樹的必經之路。建議讀者:
unique_ptr 重寫記憶體管理std::map 底層紅黑樹實現(GCC libstdc++ / LLVM libc++ 源碼)代碼倉庫建議:建立個人資料結構庫,持續重構優化,面試與實戰兩不誤。