你好!这是一个非常核心的数据结构问题。
首先,我来澄清一下:二叉查找树(Binary Search Tree, BST) 和 二叉排序树(Binary Sort Tree) 是 完全相同的概念,只是名字不同。它们都描述的是同一种数据结构。
🌳 什么是二叉查找树 (BST)?
二叉查找树(BST)是一种特殊的二叉树,它“有序”地组织数据,其定义如下:
它首先是一棵二叉树(每个节点最多有两个子节点)。
对于树中的任意一个节点,其左子树中所有节点的值都小于该节点的值。
对于树中的任意一个节点,其右子树中所有节点的值都大于该节点的值。
它的左、右子树也分别是二叉查找树。
注意: 这个定义通常不允许重复值。如果允许重复值,一种常见的约定是将其放在右子树(即右子树的值 >= 节点的值)。
🧠 主要实现什么功能?
二叉查找树的核心功能是提供高效的动态集合操作。它的主要优势在于:
高效查找 (Search):
这是它最主要的功能。要查找一个值,你从根节点开始比较:
如果值相等,就找到了。
如果值小于当前节点,就去左子树找。
如果值大于当前节点,就去右子树找。
在理想情况下(树比较“平衡”),每次比较都能排除掉大约一半的节点,因此查找的时间复杂度是 $O(\log n)$。
最坏情况: 如果树退化成一个链表(例如,依次插入1, 2, 3, 4, 5),查找时间会退化到 $O(n)$。
高效插入 (Insert) 和删除 (Delete):
排序 (Sorting):
- 这也是它被称为“二叉排序树”的原因。如果你对一棵二叉查找树进行中序遍历(In-order Traversal,即“左 -> 根 -> 右”的顺序),你会得到一个严格递增的有序序列。
💻 C 语言代码实现
下面是一个二叉查找树在 C 语言中的基本实现,包括:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
| #include <stdio.h> #include <stdlib.h>
struct Node { int data; struct Node* left; struct Node* right; };
struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); if (newNode == NULL) { printf("内存分配失败!\n"); exit(1); } newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; }
struct Node* insert(struct Node* node, int data) { if (node == NULL) { return createNode(data); }
if (data < node->data) { node->left = insert(node->left, data); } else if (data > node->data) { node->right = insert(node->right, data); }
return node; }
struct Node* search(struct Node* root, int data) { if (root == NULL) { return NULL; } if (root->data == data) { return root; }
if (data < root->data) { return search(root->left, data); } else { return search(root->right, data); } }
void inOrder(struct Node* root) { if (root != NULL) { inOrder(root->left); printf("%d ", root->data); inOrder(root->right); } }
struct Node* findMin(struct Node* node) { struct Node* current = node; while (current && current->left != NULL) { current = current->left; } return current; }
struct Node* deleteNode(struct Node* root, int data) { if (root == NULL) { return root; }
if (data < root->data) { root->left = deleteNode(root->left, data); } else if (data > root->data) { root->right = deleteNode(root->right, data); } else { if (root->left == NULL) { struct Node* temp = root->right; free(root); return temp; } else if (root->right == NULL) { struct Node* temp = root->left; free(root); return temp; }
struct Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data); } return root; }
void freeTree(struct Node* node) { if (node == NULL) return; freeTree(node->left); freeTree(node->right); free(node); }
int main() { struct Node* root = NULL;
root = insert(root, 50); insert(root, 30); insert(root, 20); insert(root, 40); insert(root, 70); insert(root, 60); insert(root, 80);
printf("中序遍历 (排序结果): "); inOrder(root); printf("\n");
int keyToSearch = 40; if (search(root, keyToSearch) != NULL) { printf("找到了 %d\n", keyToSearch); } else { printf("未找到 %d\n", keyToSearch); }
keyToSearch = 90; if (search(root, keyToSearch) != NULL) { printf("找到了 %d\n", keyToSearch); } else { printf("未找到 %d\n", keyToSearch); } printf("\n删除节点 20 (叶子节点)\n"); root = deleteNode(root, 20); printf("中序遍历: "); inOrder(root); printf("\n");
printf("\n删除节点 30 (只有一个子节点)\n"); root = deleteNode(root, 30); printf("中序遍历: "); inOrder(root); printf("\n");
printf("\n删除节点 50 (有两个子节点)\n"); root = deleteNode(root, 50); printf("中序遍历: "); inOrder(root); printf("\n");
freeTree(root);
return 0; }
|
总结
二叉查找树 (BST) 和 二叉排序树 是同义词。
核心特性: 左 < 根 < 右。
主要功能: 高效的查找、插入、删除(平均 $O(\log n)$)和排序(通过中序遍历)。
最大缺点: 在最坏情况下会退化成链表($O(n)$),这导致了更高级的平衡二叉查找树(如 AVL 树和红黑树)的出现。
你是否想了解更多关于二叉查找树的平衡问题(比如AVL树或红黑树)?