二叉查找树 BST
定义
这里给出平衡二叉树的一个实现。
二叉查找树是一种特殊的二叉树,又称为二叉排序树、二叉搜索树。
这里给出一些经典的二叉查找树的题目:
递归定义如下:
- 节点的左子树仅包含键值小于节点键值的节点。
- 节点的右子树仅包含键大于或等于节点的键的节点。
- 左和右子树都必须也是二叉搜索树。
这里主要是要对二叉树插入结点和删除结点做出说明:
插入结点
// 插入结点,记得带上取地址符
void insert(node* &root, int v) {
if(root == NULL) {
root = new node(v);
return;
}else if(v == root->data) {
return; // 已经存在则不必继续
}
else if(v < root->data) {
// 键值小于当前结点值的放到左边
insert(root->left, v);
}else {
insert(root->right, v);
}
}
删除结点
两种方法:
- 寻找比删除结点 大 的 最小结点(后驱)
- 寻找比删除结点 小 的 最大结点
然后将原结点删除,新找到的结点替换原来的位置。
思路:
- 如果当前结点为空,说明不存在该结点
- 如果当前结点 root 的权值恰好为给定的权值 x,那么说明找到来想要删除的结点
- 如果当前结点 root 不存在左右孩子,说明是叶子结点,直接删除
- 如果存在左孩子,则在左子树中寻找结点前驱 pre,然后让 pre 的数据覆盖root,接着在左子树中删除结点 pre
- 如果存在右孩子,则在右子树中寻找结点前驱 next,然后让 next 的数据覆盖root,接着在右子树中删除结点 next
- 如果当前结点 root 的权值大于给定的权值,则在左子树中递归删除 x
- 如果当前结点 root 的权值小于给定的权值,则在右子树中递归删除 x
// 寻找最大的结点
node* findMax(node* root) {
while(root->right != NULL) {
root = root->right;
}
return root;
}
node* findMin(node* root) {
while (root->left != NULL)
{
root = root->left;
}
return root;
}
void deleteNode(node* &root, int x) {
if(root == NULL) return;
if(root->data == x) {
if(root->left == NULL && root->right == NULL) {
root = NULL; // 叶子结点直接删除
}// 左子树和右子树只需要选择一种
else if(root->left != NULL) {
// 左子树不为空,则去左子树中寻找最大的值
node* pre = findMax(root->left);
root->data = pre->data;
deleteNode(root->left, pre->data); // 直接调用本身来进行删除
}else if(root->right != NULL) {
// 右子树不为空
node* next = findMin(root->right);
root->data = next->data;
deleteNode(root->right, next->data);
}
}else if(x < root->data) {
deleteNode(root->left, x);
}else {
deleteNode(root->right, x);
}
}
查找结点
由于二叉查找树是有序的二叉树,所以可以在 logN 的时间内查找某个结点。
void search(node* root, int key) {
if(root == NULL) {
printf("查找失败\n");
return;
}
if(root->data == key) {
printf("find: %d\n", root->data);
}else if(key < root->data) {
// 比该结点小,则去左子树寻找
search(root->left, key);
}else {
// 大于等于该结点,去右子树寻找
search(root->right, key);
}
}