3-2 二叉搜索树
二叉搜索树(Binary Search Tree)
二叉搜索树(Binary Search Tree,简称 BST)是一种特殊的二叉树数据结构。它的每个节点最多有两个子节点,并且满足以下核心性质:
- 左子树(Left Subtree)中所有节点的值 小于 当前节点的值
- 右子树(Right Subtree)中所有节点的值 大于 当前节点的值
- 左右子树本身也是二叉搜索树
下面是一棵典型的 BST:
8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13
在这棵树中,以节点 3 为例:它的左子节点 1 比它小,右子节点 6 比它大,而 6 的左子节点 4 和右子节点 7 也都满足 BST 性质。对任意节点执行中序遍历,都能得到一个有序序列——这是 BST 最有用的特性之一。
节点定义
BST 的基本单元是节点(Node)。每个节点包含三个要素:存储的数据、指向左子节点的指针、指向右子节点的指针。
// C++ Node definition
struct Node {
int data;
Node* left;
Node* right;
// Constructor: create a leaf node with given value
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
// C Node definition
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
// Create a new node with given value
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
# Python Node definition
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
// Go Node definition
type Node struct {
Data int
Left *Node
Right *Node
}
// Create a new node with given value
func NewNode(val int) *Node {
return &Node{Data: val, Left: nil, Right: nil}
}
C++ 使用 struct 配合构造函数初始化节点,指针默认为 nullptr;C 语言使用 typedef 定义结构体,并提供 createNode 函数手动分配内存;Python 用类(Class)的 __init__ 方法完成初始化;Go 使用结构体(Struct)定义节点类型,通过 NewNode 构造函数返回指向新节点的指针,Go 的垃圾回收机制自动管理内存。
插入操作
插入(Insertion)的核心思路是:从根节点开始,将待插入值与当前节点比较——如果更小则走向左子树,如果更大则走向右子树,直到找到一个空位置插入新节点。
例如,向上述 BST 中插入值 5:5 < 8 走左边,5 > 3 走右边,5 < 6 走左边,此时左子节点为空,将 5 插入此处。
8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13
/
5 <-- newly inserted
#include <iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
// Insert a value into the BST, return the root
Node* insert(Node* root, int val) {
// Base case: found empty spot, create new node
if (root == nullptr) {
return new Node(val);
}
// Recurse left if value is smaller
if (val < root->data) {
root->left = insert(root->left, val);
}
// Recurse right if value is larger
else if (val > root->data) {
root->right = insert(root->right, val);
}
// Duplicate values are not inserted
return root;
}
// Inorder traversal: left -> root -> right
void inorder(Node* root) {
if (root == nullptr) return;
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
int main() {
Node* root = nullptr;
// Build the example tree
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
for (int v : values) {
root = insert(root, v);
}
cout << "Inorder traversal: ";
inorder(root);
cout << endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Insert a value into the BST, return the root
Node* insert(Node* root, int val) {
if (root == NULL) {
return createNode(val);
}
if (val < root->data) {
root->left = insert(root->left, val);
} else if (val > root->data) {
root->right = insert(root->right, val);
}
return root;
}
// Inorder traversal
void inorder(Node* root) {
if (root == NULL) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
int main() {
Node* root = NULL;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = insert(root, values[i]);
}
printf("Inorder traversal: ");
inorder(root);
printf("\n");
return 0;
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def insert(root, val):
"""Insert a value into the BST, return the root."""
if root is None:
return Node(val)
if val < root.data:
root.left = insert(root.left, val)
elif val > root.data:
root.right = insert(root.right, val)
# Duplicate values are not inserted
return root
def inorder(root):
"""Inorder traversal: left -> root -> right."""
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
if __name__ == "__main__":
root = None
values = [8, 3, 10, 1, 6, 14, 4, 7, 13]
for v in values:
root = insert(root, v)
print("Inorder traversal:", end=" ")
inorder(root)
print()
package main
import "fmt"
type Node struct {
Data int
Left *Node
Right *Node
}
func NewNode(val int) *Node {
return &Node{Data: val}
}
// Insert a value into the BST, return the root
func Insert(root *Node, val int) *Node {
if root == nil {
return NewNode(val)
}
if val < root.Data {
root.Left = Insert(root.Left, val)
} else if val > root.Data {
root.Right = Insert(root.Right, val)
}
// Duplicate values are not inserted
return root
}
// Inorder traversal: left -> root -> right
func Inorder(root *Node) {
if root == nil {
return
}
Inorder(root.Left)
fmt.Print(root.Data, " ")
Inorder(root.Right)
}
func main() {
var root *Node
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, v := range values {
root = Insert(root, v)
}
fmt.Print("Inorder traversal: ")
Inorder(root)
fmt.Println()
}
上述代码按顺序插入 {8, 3, 10, 1, 6, 14, 4, 7, 13} 构建 BST,然后执行中序遍历来验证插入结果。注意 Insert 函数返回(子树的)根节点,递归时通过赋值更新父节点的左/右指针。
运行该程序将输出:
Inorder traversal: 1 3 4 6 7 8 10 13 14
中序遍历的结果恰好是一个升序序列,这验证了 BST 性质被正确维护。
搜索操作
搜索(Search)的逻辑与插入类似:从根节点开始比较目标值——相等则找到,更小则递归搜索左子树,更大则递归搜索右子树。如果递归到空节点,说明目标值不存在。
#include <iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
Node* insert(Node* root, int val) {
if (root == nullptr) return new Node(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
// Search for a value, return the node if found, nullptr otherwise
Node* search(Node* root, int val) {
// Base case: reached null or found the value
if (root == nullptr || root->data == val) {
return root;
}
// Search left subtree if value is smaller
if (val < root->data) {
return search(root->left, val);
}
// Search right subtree if value is larger
return search(root->right, val);
}
int main() {
Node* root = nullptr;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
for (int v : values) {
root = insert(root, v);
}
int targets[] = {7, 5};
for (int t : targets) {
Node* result = search(root, t);
if (result != nullptr) {
cout << "Found " << t << " in BST." << endl;
} else {
cout << t << " not found in BST." << endl;
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { exit(1); }
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int val) {
if (root == NULL) return createNode(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
// Search for a value, return pointer to node or NULL
Node* search(Node* root, int val) {
if (root == NULL || root->data == val) {
return root;
}
if (val < root->data) {
return search(root->left, val);
}
return search(root->right, val);
}
int main() {
Node* root = NULL;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = insert(root, values[i]);
}
int targets[] = {7, 5};
for (int i = 0; i < 2; i++) {
Node* result = search(root, targets[i]);
if (result != NULL) {
printf("Found %d in BST.\n", targets[i]);
} else {
printf("%d not found in BST.\n", targets[i]);
}
}
return 0;
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def insert(root, val):
if root is None:
return Node(val)
if val < root.data:
root.left = insert(root.left, val)
elif val > root.data:
root.right = insert(root.right, val)
return root
def search(root, val):
"""Search for a value, return the node if found, None otherwise."""
if root is None or root.data == val:
return root
if val < root.data:
return search(root.left, val)
return search(root.right, val)
if __name__ == "__main__":
root = None
values = [8, 3, 10, 1, 6, 14, 4, 7, 13]
for v in values:
root = insert(root, v)
for t in [7, 5]:
result = search(root, t)
if result is not None:
print(f"Found {t} in BST.")
else:
print(f"{t} not found in BST.")
package main
import "fmt"
type Node struct {
Data int
Left *Node
Right *Node
}
func NewNode(val int) *Node {
return &Node{Data: val}
}
func Insert(root *Node, val int) *Node {
if root == nil {
return NewNode(val)
}
if val < root.Data {
root.Left = Insert(root.Left, val)
} else if val > root.Data {
root.Right = Insert(root.Right, val)
}
return root
}
// Search for a value, return the node if found, nil otherwise
func Search(root *Node, val int) *Node {
if root == nil || root.Data == val {
return root
}
if val < root.Data {
return Search(root.Left, val)
}
return Search(root.Right, val)
}
func main() {
var root *Node
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, v := range values {
root = Insert(root, v)
}
targets := []int{7, 5}
for _, t := range targets {
result := Search(root, t)
if result != nil {
fmt.Printf("Found %d in BST.\n", t)
} else {
fmt.Printf("%d not found in BST.\n", t)
}
}
}
搜索 7 时,路径为 8 -> 3 -> 6 -> 7,找到目标。搜索 5 时,路径为 8 -> 3 -> 6 -> 4,到达 4 的左子节点(为空),未找到。
运行该程序将输出:
Found 7 in BST.
5 not found in BST.
遍历操作
二叉树有三种经典的深度优先遍历(Depth-First Traversal)方式,区别在于访问根节点的时机:
- 中序遍历(Inorder Traversal):先访问左子树,再访问根节点,最后访问右子树(左 - 根 - 右)。在 BST 中结果是有序的。
- 前序遍历(Preorder Traversal):先访问根节点,再访问左子树,最后访问右子树(根 - 左 - 右)。
- 后序遍历(Postorder Traversal):先访问左子树,再访问右子树,最后访问根节点(左 - 右 - 根)。
对于我们的示例树,三种遍历的结果分别为:
| 遍历方式 | 结果 |
|---|---|
| 中序(Inorder) | 1 3 4 6 7 8 10 13 14 |
| 前序(Preorder) | 8 3 1 6 4 7 10 14 13 |
| 后序(Postorder) | 1 4 7 6 3 13 14 10 8 |
#include <iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
Node* insert(Node* root, int val) {
if (root == nullptr) return new Node(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
// Inorder: left -> root -> right
void inorder(Node* root) {
if (root == nullptr) return;
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
// Preorder: root -> left -> right
void preorder(Node* root) {
if (root == nullptr) return;
cout << root->data << " ";
preorder(root->left);
preorder(root->right);
}
// Postorder: left -> right -> root
void postorder(Node* root) {
if (root == nullptr) return;
postorder(root->left);
postorder(root->right);
cout << root->data << " ";
}
int main() {
Node* root = nullptr;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
for (int v : values) {
root = insert(root, v);
}
cout << "Inorder: ";
inorder(root);
cout << endl;
cout << "Preorder: ";
preorder(root);
cout << endl;
cout << "Postorder: ";
postorder(root);
cout << endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { exit(1); }
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int val) {
if (root == NULL) return createNode(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
void inorder(Node* root) {
if (root == NULL) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
void preorder(Node* root) {
if (root == NULL) return;
printf("%d ", root->data);
preorder(root->left);
preorder(root->right);
}
void postorder(Node* root) {
if (root == NULL) return;
postorder(root->left);
postorder(root->right);
printf("%d ", root->data);
}
int main() {
Node* root = NULL;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = insert(root, values[i]);
}
printf("Inorder: ");
inorder(root);
printf("\n");
printf("Preorder: ");
preorder(root);
printf("\n");
printf("Postorder: ");
postorder(root);
printf("\n");
return 0;
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def insert(root, val):
if root is None:
return Node(val)
if val < root.data:
root.left = insert(root.left, val)
elif val > root.data:
root.right = insert(root.right, val)
return root
def inorder(root):
"""Inorder: left -> root -> right."""
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
def preorder(root):
"""Preorder: root -> left -> right."""
if root is None:
return
print(root.data, end=" ")
preorder(root.left)
preorder(root.right)
def postorder(root):
"""Postorder: left -> right -> root."""
if root is None:
return
postorder(root.left)
postorder(root.right)
print(root.data, end=" ")
if __name__ == "__main__":
root = None
values = [8, 3, 10, 1, 6, 14, 4, 7, 13]
for v in values:
root = insert(root, v)
print("Inorder: ", end=" ")
inorder(root)
print()
print("Preorder: ", end=" ")
preorder(root)
print()
print("Postorder:", end=" ")
postorder(root)
print()
package main
import "fmt"
type Node struct {
Data int
Left *Node
Right *Node
}
func NewNode(val int) *Node {
return &Node{Data: val}
}
func Insert(root *Node, val int) *Node {
if root == nil {
return NewNode(val)
}
if val < root.Data {
root.Left = Insert(root.Left, val)
} else if val > root.Data {
root.Right = Insert(root.Right, val)
}
return root
}
// Inorder: left -> root -> right
func Inorder(root *Node) {
if root == nil {
return
}
Inorder(root.Left)
fmt.Print(root.Data, " ")
Inorder(root.Right)
}
// Preorder: root -> left -> right
func Preorder(root *Node) {
if root == nil {
return
}
fmt.Print(root.Data, " ")
Preorder(root.Left)
Preorder(root.Right)
}
// Postorder: left -> right -> root
func Postorder(root *Node) {
if root == nil {
return
}
Postorder(root.Left)
Postorder(root.Right)
fmt.Print(root.Data, " ")
}
func main() {
var root *Node
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, v := range values {
root = Insert(root, v)
}
fmt.Print("Inorder: ")
Inorder(root)
fmt.Println()
fmt.Print("Preorder: ")
Preorder(root)
fmt.Println()
fmt.Print("Postorder: ")
Postorder(root)
fmt.Println()
}
运行该程序将输出:
Inorder: 1 3 4 6 7 8 10 13 14
Preorder: 8 3 1 6 4 7 10 14 13
Postorder: 1 4 7 6 3 13 14 10 8
注意中序遍历的结果 1 3 4 6 7 8 10 13 14 恰好是升序排列——这是 BST 最核心的性质之一。
删除操作
删除(Deletion)是 BST 中最复杂的操作,需要处理三种情况:
- 叶子节点(Leaf Node):直接删除,父节点对应指针置空。
- 只有一个子节点(One Child):用子节点替换被删除节点。
- 有两个子节点(Two Children):找到中序后继(Inorder Successor),即右子树中的最小值节点,用它的值替换被删除节点的值,然后删除那个后继节点。
下面依次演示删除 1(叶子)、10(一个子节点)、3(两个子节点)。
Original: Delete 1 (leaf): Delete 10 (one child):
8 8 8
/ \ / \ / \
3 10 3 10 3 14
/ \ \ / \ \ / \ /
1 6 14 6 14 6 13
/ \ / / \ / / \
4 7 13 4 7 13 4 7
Delete 3 (two children, successor = 4):
8
/ \
4 14
/ \ /
6 13
/ \
(4) 7
Note: 3's inorder successor is 4 (right subtree minimum).
Replace 3 with 4, then delete the original 4 node.
#include <iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
Node* insert(Node* root, int val) {
if (root == nullptr) return new Node(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
// Find the node with minimum value in a subtree
Node* findMin(Node* root) {
while (root->left != nullptr) {
root = root->left;
}
return root;
}
// Delete a value from the BST, return the new root
Node* deleteNode(Node* root, int val) {
if (root == nullptr) return root;
if (val < root->data) {
root->left = deleteNode(root->left, val);
} else if (val > root->data) {
root->right = deleteNode(root->right, val);
} else {
// Found the node to delete
// Case 1 & 2: node with 0 or 1 child
if (root->left == nullptr) {
Node* temp = root->right;
delete root;
return temp;
} else if (root->right == nullptr) {
Node* temp = root->left;
delete root;
return temp;
}
// Case 3: node with two children
// Find inorder successor (smallest in right subtree)
Node* temp = findMin(root->right);
root->data = temp->data; // Replace with successor's value
root->right = deleteNode(root->right, temp->data); // Delete successor
}
return root;
}
void inorder(Node* root) {
if (root == nullptr) return;
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
int main() {
Node* root = nullptr;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
for (int v : values) {
root = insert(root, v);
}
cout << "Original: ";
inorder(root);
cout << endl;
// Case 1: delete leaf node
root = deleteNode(root, 1);
cout << "After delete 1: ";
inorder(root);
cout << endl;
// Case 2: delete node with one child
root = deleteNode(root, 10);
cout << "After delete 10:";
inorder(root);
cout << endl;
// Case 3: delete node with two children
root = deleteNode(root, 3);
cout << "After delete 3: ";
inorder(root);
cout << endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { exit(1); }
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int val) {
if (root == NULL) return createNode(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
Node* findMin(Node* root) {
while (root->left != NULL) {
root = root->left;
}
return root;
}
Node* deleteNode(Node* root, int val) {
if (root == NULL) return root;
if (val < root->data) {
root->left = deleteNode(root->left, val);
} else if (val > root->data) {
root->right = deleteNode(root->right, val);
} else {
if (root->left == NULL) {
Node* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
void inorder(Node* root) {
if (root == NULL) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
int main() {
Node* root = NULL;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = insert(root, values[i]);
}
printf("Original: ");
inorder(root);
printf("\n");
root = deleteNode(root, 1);
printf("After delete 1: ");
inorder(root);
printf("\n");
root = deleteNode(root, 10);
printf("After delete 10: ");
inorder(root);
printf("\n");
root = deleteNode(root, 3);
printf("After delete 3: ");
inorder(root);
printf("\n");
return 0;
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def insert(root, val):
if root is None:
return Node(val)
if val < root.data:
root.left = insert(root.left, val)
elif val > root.data:
root.right = insert(root.right, val)
return root
def find_min(root):
"""Find the node with minimum value in a subtree."""
while root.left is not None:
root = root.left
return root
def delete_node(root, val):
"""Delete a value from the BST, return the new root."""
if root is None:
return root
if val < root.data:
root.left = delete_node(root.left, val)
elif val > root.data:
root.right = delete_node(root.right, val)
else:
# Case 1 & 2: node with 0 or 1 child
if root.left is None:
return root.right
elif root.right is None:
return root.left
# Case 3: node with two children
# Find inorder successor (smallest in right subtree)
successor = find_min(root.right)
root.data = successor.data
root.right = delete_node(root.right, successor.data)
return root
def inorder(root):
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
if __name__ == "__main__":
root = None
values = [8, 3, 10, 1, 6, 14, 4, 7, 13]
for v in values:
root = insert(root, v)
print("Original: ", end=" ")
inorder(root)
print()
root = delete_node(root, 1)
print("After delete 1: ", end=" ")
inorder(root)
print()
root = delete_node(root, 10)
print("After delete 10:", end=" ")
inorder(root)
print()
root = delete_node(root, 3)
print("After delete 3: ", end=" ")
inorder(root)
print()
package main
import "fmt"
type Node struct {
Data int
Left *Node
Right *Node
}
func NewNode(val int) *Node {
return &Node{Data: val}
}
func Insert(root *Node, val int) *Node {
if root == nil {
return NewNode(val)
}
if val < root.Data {
root.Left = Insert(root.Left, val)
} else if val > root.Data {
root.Right = Insert(root.Right, val)
}
return root
}
// Find the node with minimum value in a subtree
func FindMin(root *Node) *Node {
for root.Left != nil {
root = root.Left
}
return root
}
// Delete a value from the BST, return the new root
func DeleteNode(root *Node, val int) *Node {
if root == nil {
return root
}
if val < root.Data {
root.Left = DeleteNode(root.Left, val)
} else if val > root.Data {
root.Right = DeleteNode(root.Right, val)
} else {
// Found the node to delete
// Case 1 & 2: node with 0 or 1 child
if root.Left == nil {
return root.Right
} else if root.Right == nil {
return root.Left
}
// Case 3: node with two children
// Find inorder successor (smallest in right subtree)
successor := FindMin(root.Right)
root.Data = successor.Data
root.Right = DeleteNode(root.Right, successor.Data)
}
return root
}
func Inorder(root *Node) {
if root == nil {
return
}
Inorder(root.Left)
fmt.Print(root.Data, " ")
Inorder(root.Right)
}
func main() {
var root *Node
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, v := range values {
root = Insert(root, v)
}
fmt.Print("Original: ")
Inorder(root)
fmt.Println()
// Case 1: delete leaf node
root = DeleteNode(root, 1)
fmt.Print("After delete 1: ")
Inorder(root)
fmt.Println()
// Case 2: delete node with one child
root = DeleteNode(root, 10)
fmt.Print("After delete 10: ")
Inorder(root)
fmt.Println()
// Case 3: delete node with two children
root = DeleteNode(root, 3)
fmt.Print("After delete 3: ")
Inorder(root)
fmt.Println()
}
删除 1 是最简单的情况——它是叶子节点,直接移除即可。删除 10 时它只有一个右子节点 14,用 14 替换 10 的位置。删除 3 时它有两个子节点,找到右子树中的最小值 4(中序后继),用 4 替换 3 的值,再从右子树中删除原来的 4。
运行该程序将输出:
Original: 1 3 4 6 7 8 10 13 14
After delete 1: 3 4 6 7 8 10 13 14
After delete 10: 3 4 6 7 8 13 14
After delete 3: 4 6 7 8 13 14
每次删除后,中序遍历结果仍然保持有序。
完整实现
下面提供完整的 BST 实现,包含插入、搜索、删除以及三种遍历操作,将前面各节整合为一个可独立运行的程序。
#include <iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
// Insert a value into the BST
Node* insert(Node* root, int val) {
if (root == nullptr) return new Node(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
// Search for a value in the BST
Node* search(Node* root, int val) {
if (root == nullptr || root->data == val) return root;
if (val < root->data) return search(root->left, val);
return search(root->right, val);
}
// Find the minimum value node in a subtree
Node* findMin(Node* root) {
while (root->left != nullptr) root = root->left;
return root;
}
// Delete a value from the BST
Node* deleteNode(Node* root, int val) {
if (root == nullptr) return root;
if (val < root->data) {
root->left = deleteNode(root->left, val);
} else if (val > root->data) {
root->right = deleteNode(root->right, val);
} else {
if (root->left == nullptr) {
Node* temp = root->right;
delete root;
return temp;
} else if (root->right == nullptr) {
Node* temp = root->left;
delete root;
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
// Inorder traversal: left -> root -> right
void inorder(Node* root) {
if (root == nullptr) return;
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
// Preorder traversal: root -> left -> right
void preorder(Node* root) {
if (root == nullptr) return;
cout << root->data << " ";
preorder(root->left);
preorder(root->right);
}
// Postorder traversal: left -> right -> root
void postorder(Node* root) {
if (root == nullptr) return;
postorder(root->left);
postorder(root->right);
cout << root->data << " ";
}
int main() {
Node* root = nullptr;
// Build BST
cout << "=== Building BST ===" << endl;
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
for (int v : values) {
root = insert(root, v);
cout << "Inserted " << v << endl;
}
// Traversals
cout << "\n=== Traversals ===" << endl;
cout << "Inorder: ";
inorder(root);
cout << endl;
cout << "Preorder: ";
preorder(root);
cout << endl;
cout << "Postorder: ";
postorder(root);
cout << endl;
// Search
cout << "\n=== Search ===" << endl;
for (int t : {7, 5}) {
Node* result = search(root, t);
if (result) cout << "Found " << t << endl;
else cout << t << " not found" << endl;
}
// Delete
cout << "\n=== Deletion ===" << endl;
for (int d : {1, 10, 3}) {
root = deleteNode(root, d);
cout << "Deleted " << d << " -> Inorder: ";
inorder(root);
cout << endl;
}
// Final traversals
cout << "\n=== Final Traversals ===" << endl;
cout << "Inorder: ";
inorder(root);
cout << endl;
cout << "Preorder: ";
preorder(root);
cout << endl;
cout << "Postorder: ";
postorder(root);
cout << endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(int val) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { exit(1); }
newNode->data = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int val) {
if (root == NULL) return createNode(val);
if (val < root->data) root->left = insert(root->left, val);
else if (val > root->data) root->right = insert(root->right, val);
return root;
}
Node* search(Node* root, int val) {
if (root == NULL || root->data == val) return root;
if (val < root->data) return search(root->left, val);
return search(root->right, val);
}
Node* findMin(Node* root) {
while (root->left != NULL) root = root->left;
return root;
}
Node* deleteNode(Node* root, int val) {
if (root == NULL) return root;
if (val < root->data) {
root->left = deleteNode(root->left, val);
} else if (val > root->data) {
root->right = deleteNode(root->right, val);
} else {
if (root->left == NULL) {
Node* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
void inorder(Node* root) {
if (root == NULL) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
void preorder(Node* root) {
if (root == NULL) return;
printf("%d ", root->data);
preorder(root->left);
preorder(root->right);
}
void postorder(Node* root) {
if (root == NULL) return;
postorder(root->left);
postorder(root->right);
printf("%d ", root->data);
}
int main() {
Node* root = NULL;
printf("=== Building BST ===\n");
int values[] = {8, 3, 10, 1, 6, 14, 4, 7, 13};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = insert(root, values[i]);
printf("Inserted %d\n", values[i]);
}
printf("\n=== Traversals ===\n");
printf("Inorder: ");
inorder(root);
printf("\nPreorder: ");
preorder(root);
printf("\nPostorder: ");
postorder(root);
printf("\n");
printf("\n=== Search ===\n");
int targets[] = {7, 5};
for (int i = 0; i < 2; i++) {
Node* result = search(root, targets[i]);
if (result) printf("Found %d\n", targets[i]);
else printf("%d not found\n", targets[i]);
}
printf("\n=== Deletion ===\n");
int toDelete[] = {1, 10, 3};
for (int i = 0; i < 3; i++) {
root = deleteNode(root, toDelete[i]);
printf("Deleted %d -> Inorder: ", toDelete[i]);
inorder(root);
printf("\n");
}
printf("\n=== Final Traversals ===\n");
printf("Inorder: ");
inorder(root);
printf("\nPreorder: ");
preorder(root);
printf("\nPostorder: ");
postorder(root);
printf("\n");
return 0;
}
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def insert(root, val):
if root is None:
return Node(val)
if val < root.data:
root.left = insert(root.left, val)
elif val > root.data:
root.right = insert(root.right, val)
return root
def search(root, val):
if root is None or root.data == val:
return root
if val < root.data:
return search(root.left, val)
return search(root.right, val)
def find_min(root):
while root.left is not None:
root = root.left
return root
def delete_node(root, val):
if root is None:
return root
if val < root.data:
root.left = delete_node(root.left, val)
elif val > root.data:
root.right = delete_node(root.right, val)
else:
if root.left is None:
return root.right
elif root.right is None:
return root.left
successor = find_min(root.right)
root.data = successor.data
root.right = delete_node(root.right, successor.data)
return root
def inorder(root):
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
def preorder(root):
if root is None:
return
print(root.data, end=" ")
preorder(root.left)
preorder(root.right)
def postorder(root):
if root is None:
return
postorder(root.left)
postorder(root.right)
print(root.data, end=" ")
if __name__ == "__main__":
root = None
print("=== Building BST ===")
values = [8, 3, 10, 1, 6, 14, 4, 7, 13]
for v in values:
root = insert(root, v)
print(f"Inserted {v}")
print("\n=== Traversals ===")
print("Inorder: ", end=" ")
inorder(root)
print()
print("Preorder: ", end=" ")
preorder(root)
print()
print("Postorder:", end=" ")
postorder(root)
print()
print("\n=== Search ===")
for t in [7, 5]:
result = search(root, t)
if result:
print(f"Found {t}")
else:
print(f"{t} not found")
print("\n=== Deletion ===")
for d in [1, 10, 3]:
root = delete_node(root, d)
print(f"Deleted {d} -> Inorder:", end=" ")
inorder(root)
print()
print("\n=== Final Traversals ===")
print("Inorder: ", end=" ")
inorder(root)
print()
print("Preorder: ", end=" ")
preorder(root)
print()
print("Postorder:", end=" ")
postorder(root)
print()
package main
import "fmt"
type Node struct {
Data int
Left *Node
Right *Node
}
func NewNode(val int) *Node {
return &Node{Data: val}
}
// Insert a value into the BST
func Insert(root *Node, val int) *Node {
if root == nil {
return NewNode(val)
}
if val < root.Data {
root.Left = Insert(root.Left, val)
} else if val > root.Data {
root.Right = Insert(root.Right, val)
}
return root
}
// Search for a value in the BST
func Search(root *Node, val int) *Node {
if root == nil || root.Data == val {
return root
}
if val < root.Data {
return Search(root.Left, val)
}
return Search(root.Right, val)
}
// Find the minimum value node in a subtree
func FindMin(root *Node) *Node {
for root.Left != nil {
root = root.Left
}
return root
}
// Delete a value from the BST
func DeleteNode(root *Node, val int) *Node {
if root == nil {
return root
}
if val < root.Data {
root.Left = DeleteNode(root.Left, val)
} else if val > root.Data {
root.Right = DeleteNode(root.Right, val)
} else {
if root.Left == nil {
return root.Right
} else if root.Right == nil {
return root.Left
}
successor := FindMin(root.Right)
root.Data = successor.Data
root.Right = DeleteNode(root.Right, successor.Data)
}
return root
}
// Inorder traversal: left -> root -> right
func Inorder(root *Node) {
if root == nil {
return
}
Inorder(root.Left)
fmt.Print(root.Data, " ")
Inorder(root.Right)
}
// Preorder traversal: root -> left -> right
func Preorder(root *Node) {
if root == nil {
return
}
fmt.Print(root.Data, " ")
Preorder(root.Left)
Preorder(root.Right)
}
// Postorder traversal: left -> right -> root
func Postorder(root *Node) {
if root == nil {
return
}
Postorder(root.Left)
Postorder(root.Right)
fmt.Print(root.Data, " ")
}
func main() {
var root *Node
// Build BST
fmt.Println("=== Building BST ===")
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, v := range values {
root = Insert(root, v)
fmt.Printf("Inserted %d\n", v)
}
// Traversals
fmt.Println("\n=== Traversals ===")
fmt.Print("Inorder: ")
Inorder(root)
fmt.Println()
fmt.Print("Preorder: ")
Preorder(root)
fmt.Println()
fmt.Print("Postorder: ")
Postorder(root)
fmt.Println()
// Search
fmt.Println("\n=== Search ===")
for _, t := range []int{7, 5} {
result := Search(root, t)
if result != nil {
fmt.Printf("Found %d\n", t)
} else {
fmt.Printf("%d not found\n", t)
}
}
// Delete
fmt.Println("\n=== Deletion ===")
for _, d := range []int{1, 10, 3} {
root = DeleteNode(root, d)
fmt.Printf("Deleted %d -> Inorder: ", d)
Inorder(root)
fmt.Println()
}
// Final traversals
fmt.Println("\n=== Final Traversals ===")
fmt.Print("Inorder: ")
Inorder(root)
fmt.Println()
fmt.Print("Preorder: ")
Preorder(root)
fmt.Println()
fmt.Print("Postorder: ")
Postorder(root)
fmt.Println()
}
运行该程序将输出:
=== Building BST ===
Inserted 8
Inserted 3
Inserted 10
Inserted 1
Inserted 6
Inserted 14
Inserted 4
Inserted 7
Inserted 13
=== Traversals ===
Inorder: 1 3 4 6 7 8 10 13 14
Preorder: 8 3 1 6 4 7 10 14 13
Postorder: 1 4 7 6 3 13 14 10 8
=== Search ===
Found 7
5 not found
=== Deletion ===
Deleted 1 -> Inorder: 3 4 6 7 8 10 13 14
Deleted 10 -> Inorder: 3 4 6 7 8 13 14
Deleted 3 -> Inorder: 4 6 7 8 13 14
=== Final Traversals ===
Inorder: 4 6 7 8 13 14
Preorder: 8 4 6 7 14 13
Postorder: 7 6 4 13 14 8
BST的性质
下表总结了 BST 各操作的时间复杂度:
| 操作 | 平均情况(Average) | 最坏情况(Worst) |
|---|---|---|
| 搜索(Search) | O(log n) | O(n) |
| 插入(Insert) | O(log n) | O(n) |
| 删除(Delete) | O(log n) | O(n) |
| 中序遍历(Inorder Traversal) | O(n) | O(n) |
关键说明:
- 平均情况 O(log n):当 BST 比较平衡时,每次比较排除约一半节点,搜索路径长度为树的高度 h,平衡树的 h 约为 log(n)。
- 最坏情况 O(n):当插入的数据已经有序时(例如依次插入 1, 2, 3, 4, 5),BST 会退化(Degenerate)为一条链表(Linked List),所有节点只有右子节点。此时搜索、插入、删除都需要遍历整棵树。
- 中序遍历性质:无论树的形状如何,BST 的中序遍历始终产生一个有序序列。这一性质可用于验证 BST 的正确性,也可用于排序。
- 空间复杂度:递归实现的栈空间为 O(h),其中 h 是树的高度。平衡时为 O(log n),退化时为 O(n)。
为了避免最坏情况,实践中常使用自平衡二叉搜索树(Self-balancing BST),如 AVL 树(AVL Tree)或红黑树(Red-Black Tree),它们通过旋转操作保证树的高度始终维持在 O(log n)。

浙公网安备 33010602011771号