二叉搜索树
二叉查找树(Binary Search Tree),也称二叉搜索树、有序二叉树(ordered binary tree),排序二叉树(orted binary tree)
特点:
- 二叉树
- 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值
- 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值
- 任意节点的左,右子树也分别为二叉查找树
- 没有键值相等的节点
注:
堆
必须是完全二叉树- 二叉搜索树不一定是完全二叉树
优势
二叉搜索相比其他数据结构在查找和插入的复杂度较低. 均为 O(logN).
它是基础的数据结构,可用于构建更抽象的数据结构,如集合,映射等.
常用操作
0. 定义:
用一个根节点表示一个二叉搜索树
节点的结构如下所示:
template<typename Key,typename Value>
class BST {
private:
struct Node {
Key key;
Value value;
Node *left;
Node *right;
Node(key key, Value value) {
this->key = key;
this->value = value;
this->left = this->right = NULL;
}
};
Node *root;
int count;
public:
BST() {
root = NULL;
count = 0;
}
~BST() {
// TODO:
}
}
1. 查找
在二叉搜索树 root
中查找 key
是否存在
bool contains(Node* node, Key key) {
if (node == NULL)
return NULL;
if (node->key > key) {
return contains(node->left, key);
}
else if (node->key < key) {
return contains(node->right, key);
}
else {
return true;
}
}
2.插入
插入和查找是一样的
// 将(key,value)插入二叉搜索树中,返回根节点
Node* insert(Key key,Value value) {
root = insert(root, key,value);
return root;
}
Node* insert(Node *node, Key key, Value value) {
if (node == NULL) {
count++;
root = new Node(key, value);
} else {
if (key == node->key) {
node->value = value;
}
else if (key > node->key) {
node->right = insert(node->right,key,value);
}
else{
// key < node->key
node->left = insert(node->left, key, value);
}
}
return node;
}
3. 删除
删除分为3种情况:
- 只有左孩子,则将左孩子返回
- 只有右孩子,则将右孩子返回
- 左右孩子都有,找到这个节点的后继节点,再删除右子树中的最小节点.将后继节点的左孩子指向当前的左孩子.然后返回后继节点.
// 将关键字为key的节点,返回根节点
Node* delete(Key key) {
root = delete(root, key);
}
//
Node* delete(Node* node, Key key) {
if (node == NULL) {
return NULL;
}
if (node->key < key) {
// 在左子树中删除,返回根节点的左孩子
node->left = delete(node->left, key);
return node;
}
else if (node->key > key) {
// 在右子树中删除,返回根节点的右孩子
node->right = delete(node->right, key);
return node;
}
else {// 找到了该节点
// 若左孩子为空,那么则返回其右孩子
if (node->left == NULL) {
Node* rightNode = node->right;
node->right = NULL;
size--;
return rightNode;
}
// 若右孩子为空,那么则返回其左孩子
else if (node->right == NULL) {
Node* leftNode = node->left;
node->left = NULL;
size--;
return leftNode;
}
else {
// 如果二者都不为空,在右子树找最小值结点,即后继节点
Node* successor = minimum(node->right);
// 将这个最小值结点删除
successor->right = deleteMin(node->right);
// 将原来节点的左子树付给它
successor->left = node->left;
// 删除Node
node->left = node->right = NULL;
// 返回这个节点
return successor;
}
}
}
// 递归找最小值节点
Node* minimum(Node* node) {
if (node->left == NULL){
return node;
}
return minimum(node->left);
}
// 递归找最大值节点
Node* Maximum(Node* node) {
if (node->right == NULL) {
return node;
}
return Maximum(node->right);
}
Node* deleteMin(Node* node) {
if (node->left == NULL) {
Node* rightNode = node->right;
node->right = NULL;
size--;
return rightNode;
}
node->left = deleteMin(node->left);
return node;
}
Node* deleteMax(Node* node) {
if (node->right == NULL) {
Node* leftNode = node->left;
node->left = NULL;
size--;
return leftNode;
}
node->right = deleteMin(node->right);
return node;
}
4.遍历
中序遍历有序