定义
typedef struct node{
int key;
node* p = NULL; //存储其父结点
node* left = NULL; //存储其左子结点
node* right = NULL; //存储其右子结点
}Node;
搜索操作
Node* BST_Search(Node* node, int k)
{
if (node == NULL || node->key == k) return node; //树为空 或 根结点即为要找的结点
if(node->key > k) return BST_Search(node -> left, k); //查找左子树
else return BST_Search(node -> right, k); //查找右子树
}
返回最小值/最大值结点
Node* BST_minimum(Node* node) //两个操作是对称的
{
while(node -> left != NULL)
node = node -> left;
return node;
}
Node* BST_maximum(Node* node)
{
while (node -> right != NULL)
node = node -> right;
return node;
}
中序遍历
void in_order_search(Node* node)
{
if(node != NULL)
{
in_order_search(node->left); //先搜索左子树
cout << node -> key; //再搜素根节点
in_order_search(node -> right); //最后搜索右子树
}
}
返回一个结点的后继
一个结点的后续(successor)为关键字大于当前结点的最小结点
Node* BST_successor(Node* node) //与返回前驱的操作对称
{
// 若传入根节点但没有右子节点 则其为最大关键字 返回NULL
// 一个结点的前驱可能在右子树(如果该结点存在右子结点)即右子树中的最小结点
// 也可能在祖宗结点上(不存在右子结点)即路径上第一个大于该结点的祖宗结点
if(node -> right != NULL)
return BST_minimum(node -> right);
Node* par = node->p;
while(par != NULL && node == par->right)
{
node = par;
par = par -> p;
}
return par;
}
返回一个结点的前驱
Node* BST_predecessor(Node* node)
{
// 若传入根节点但没有右子节点 则其为最小关键字 返回NULL
if(node -> left != NULL)
return BST_maximum(node -> left);
Node* par = node->p;
while(par != NULL && node == par -> left)
{
node = par;
par = par -> p;
}
return par;
}
插入结点
void BST_insert(Node* &root, Node* z)
{
// 从根结点出发寻找合适插入该结点的叶结点位置
// 换句话说,插入操作一定是插入在叶结点上(由二叉树的性质知道这是一定可以做到的)
// 因为一定存在一种偏序关系使新结点可以不断"下沉"
Node* y = NULL;
Node* x = root;
while(x != NULL)
{
y = x;
if(z -> key < x -> key)
x = x -> left;
else
x = x -> right;
}
if(y == NULL) root = z; // 说明为空树
else if (z -> key < y -> key) y->left = z; // 作为 y 的左子结点
else y -> right = z; // 作为 y 的右子结点
}
取代操作(删除操作中会用到)
void BST_transplant(Node* &root, Node* u, Node* v) //用 v 取代 u
{
if(u -> p == NULL) root = v;
else if (u == u->p->left) u->p->left = v;
else u->p->right = v;
if(v != NULL)
v->p = u->p;
}
删除操作
void BST_delete(Node* root, Node* z)
{
// 无子结点直接删除即可
// 前两个分支分别处理只有一个子结点的情况,这个时候删除可以直接用子结点替代上来
if(z->left == NULL)
BST_transplant(root, z, z->right);
else if(z->right == NULL)
BST_transplant(root, z, z->left);
else // 处理两个结点都存在的情况
{ // 最后要用后继结点 y 来替代 才不会违反BST的性质
Node* y = BST_minimum(z->right);
// 若后继 y 不是 z 的右子结点 那么要先将 y 的右子树替代 y
// 后继 y 是不可能存在左子树的(否则真正的后继应该在为 y 的左子树中)
if(y->p != z)
{
BST_transplant(root, y, y->right);
y->right = z->right; // 将 y 结点接到 z 的右子结点之上 使其化为下面这种情况
y->right->p = y;
}
// 处理后继 y 结点直接就是 z 的右子结点的情况
BST_transplant(root, z, y); //直接用 y 取代 z 即可
y->left = z->left;
y->left->p = y;
}
}
参考资料:Introduction to Algorithm, Third Edition, Chapter 12 Binary search tree.