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 中插入值 55 < 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 中最复杂的操作,需要处理三种情况:

  1. 叶子节点(Leaf Node):直接删除,父节点对应指针置空。
  2. 只有一个子节点(One Child):用子节点替换被删除节点。
  3. 有两个子节点(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)。

posted @ 2026-04-16 11:09  游翔  阅读(7)  评论(0)    收藏  举报