本文介绍了二叉搜索树的一些必要元素,包括:
search(T key):特定键值的查找;
minimum(): 树中最小键值的查找;
maximum():树中最大键值的查找;
successor(BTNode<T>* x):获得x的下一节点;
predeccessor(BTNode<T>* x):获得x的上一节点;
insert(T data):插入指定的键值;
remove(T data):删除指定的键值;
rotateLeft(BTNode<T>* x):对x节点进行向左旋转;
rotateRight(BTNode<T>* x):对x节点进行向右旋转。
下面是完整的代码:
#ifndef _BS_TREE_H_
#define _BS_TREE_H_
#include " BTree.h "
template < class T >
class BSTree : public BTree < T >
... {
public:
BSTree(T data = T()) : BTree(data), avlnode_(BTNode<T>::nil()), rbnode_(BTNode<T>::nil())...{ }
virtual ~BSTree() ...{ }
public:
BTNode<T>* search(T key) ...{ return search(root_, key); }
BTNode<T>* minimum() ...{ return minimum(root_); }
BTNode<T>* maximum() ...{ return maximum(root_); }
BTNode<T>* successor(BTNode<T>* x)
...{
if (x->rchild_ != BTNode<T>::nil()) return minimum(x->rchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->rchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
BTNode<T>* predeccessor(BTNode<T>* x)
...{
if (x->lchild_ != BTNode<T>::nil()) return maximum(x->lchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->lchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
// The pointer x traces the path, and the pointer y is maintained as the parent of x.
// After initialization, the while loop in lines 3-7 causes these two pointers to move down the
// tree, going left or right depending on the comparison of key[z] with key[x], until x is set to
// NIL. This NIL occupies the position where we wish to place the input item z. Lines 8-13 set
// the pointers that cause z to be inserted.
virtual void insert(T data)
...{
BTNode<T>* y = BTNode<T>::nil(), *x = root_;
// x traces the path, until x is set to BTNode<T>::nil(),
// and y is the parent of x, and at last
// y must be a leaf node with no child
while (x != BTNode<T>::nil())
...{
y = x;
if (data < x->data_) x = x->lchild_;
else x = x->rchild_;
}
BTNode<T>* z = new BTNode<T>(data);
// Insert the z here, let y be the parent of z
z->parent_ = y;
// specify the current node for avltree and rbtree
avlnode_ = z->parent_;
rbnode_ = z;
// let z be the child of y
// y is BTNode<T>::nil(), this is an empty tree
if (y == BTNode<T>::nil()) root_ = z;
// insert z as y's left child
else if (data < y->data_) y->lchild_ = z;
// insert z as y's right child
else y->rchild_ = z;
}
// (a) If z has no children, we just remove it.
// (b) If z has only one child, we splice out z.
// (c) If z has two children, we splice out its successor y,
// which has at most one child, and then replace z's key
// and satellite data with y's key and satellite data
virtual void remove(T data)
...{
BTNode<T> *y = BTNode<T>::nil(), *x = BTNode<T>::nil();
BTNode<T> *z = search(data);
// can't find the node with data
if (z == BTNode<T>::nil()) return;
// at most one child, remove z or splice out z
if (z->lchild_ == BTNode<T>::nil() || z->rchild_ == BTNode<T>::nil()) y = z;
// two children, spice out its successor y
else y = successor(z);
// here we find the child to point when we spice out y
if (y->lchild_ != BTNode<T>::nil()) x = y->lchild_;
else x = y->rchild_;
// spice out y and specify the new parent of child
if (x != BTNode<T>::nil()) x->parent_ = y->parent_;
// specify the current node for rbtree and avltree
if (y->color_ == BLACK) rbnode_ = y->parent_;
else rbnode_ = BTNode<T>::nil();
avlnode_ = y->parent_;
// here we specify the new child of parent
// y is root
if (y->parent_ == BTNode<T>::nil()) root_ = x;
// y is left child
else if (y == y->parent_->lchild_) y->parent_->lchild_ = x;
// y is right child
else y->parent_->rchild_ = x;
// when y is a successor and be spiced out,
// so we replace the z's data with y's data
// and looks like z is deleted
if (y != z) z->data_ = y->data_;
delete y;
}
protected:
// transforms the configuration of the two nodes on the left into the
// configuration on the right by changing a constant number of pointers.
virtual void rotateLeft(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->rchild_;
// Turn y's left subtree into x's right subtree
x->rchild_ = y->lchild_;
if (y->lchild_ != BTNode<T>::nil()) y->lchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's left
y->lchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
// transforms the configuration of the two nodes on the right into the
// configuration on the left by changing a constant number of pointers.
virtual void rotateRight(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->lchild_;
// Turn y's left subtree into x's right subtree
x->lchild_ = y->rchild_;
if (y->rchild_ != BTNode<T>::nil()) y->rchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's right
y->rchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
private:
BTNode<T>* search(BTNode<T>* x, T key)
...{
while (x != BTNode<T>::nil() && x->data_ != key)
...{
if (key < x->data_) x = search(x->lchild_, key);
else x = search(x->rchild_, key);
}
return (x->data_ == key) ? x : BTNode<T>::nil();
}
BTNode<T>* minimum(BTNode<T>* x)
...{
while (x->lchild_ != BTNode<T>::nil()) x = x->lchild_;
return x;
}
BTNode<T>* maximum(BTNode<T>* x)
...{
while (x->rchild_ != BTNode<T>::nil()) x = x->rchild_;
return x;
}
protected:
BTNode<T>* avlnode_;
BTNode<T>* rbnode_;
} ;
#endif
#define _BS_TREE_H_
#include " BTree.h "
template < class T >
class BSTree : public BTree < T >
... {
public:
BSTree(T data = T()) : BTree(data), avlnode_(BTNode<T>::nil()), rbnode_(BTNode<T>::nil())...{ }
virtual ~BSTree() ...{ }
public:
BTNode<T>* search(T key) ...{ return search(root_, key); }
BTNode<T>* minimum() ...{ return minimum(root_); }
BTNode<T>* maximum() ...{ return maximum(root_); }
BTNode<T>* successor(BTNode<T>* x)
...{
if (x->rchild_ != BTNode<T>::nil()) return minimum(x->rchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->rchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
BTNode<T>* predeccessor(BTNode<T>* x)
...{
if (x->lchild_ != BTNode<T>::nil()) return maximum(x->lchild_);
BTNode<T>* y = x->parent_;
while (y != BTNode<T>::nil() && x == y->lchild_)
...{
x = y;
y = x->parent_;
}
return y;
}
// The pointer x traces the path, and the pointer y is maintained as the parent of x.
// After initialization, the while loop in lines 3-7 causes these two pointers to move down the
// tree, going left or right depending on the comparison of key[z] with key[x], until x is set to
// NIL. This NIL occupies the position where we wish to place the input item z. Lines 8-13 set
// the pointers that cause z to be inserted.
virtual void insert(T data)
...{
BTNode<T>* y = BTNode<T>::nil(), *x = root_;
// x traces the path, until x is set to BTNode<T>::nil(),
// and y is the parent of x, and at last
// y must be a leaf node with no child
while (x != BTNode<T>::nil())
...{
y = x;
if (data < x->data_) x = x->lchild_;
else x = x->rchild_;
}
BTNode<T>* z = new BTNode<T>(data);
// Insert the z here, let y be the parent of z
z->parent_ = y;
// specify the current node for avltree and rbtree
avlnode_ = z->parent_;
rbnode_ = z;
// let z be the child of y
// y is BTNode<T>::nil(), this is an empty tree
if (y == BTNode<T>::nil()) root_ = z;
// insert z as y's left child
else if (data < y->data_) y->lchild_ = z;
// insert z as y's right child
else y->rchild_ = z;
}
// (a) If z has no children, we just remove it.
// (b) If z has only one child, we splice out z.
// (c) If z has two children, we splice out its successor y,
// which has at most one child, and then replace z's key
// and satellite data with y's key and satellite data
virtual void remove(T data)
...{
BTNode<T> *y = BTNode<T>::nil(), *x = BTNode<T>::nil();
BTNode<T> *z = search(data);
// can't find the node with data
if (z == BTNode<T>::nil()) return;
// at most one child, remove z or splice out z
if (z->lchild_ == BTNode<T>::nil() || z->rchild_ == BTNode<T>::nil()) y = z;
// two children, spice out its successor y
else y = successor(z);
// here we find the child to point when we spice out y
if (y->lchild_ != BTNode<T>::nil()) x = y->lchild_;
else x = y->rchild_;
// spice out y and specify the new parent of child
if (x != BTNode<T>::nil()) x->parent_ = y->parent_;
// specify the current node for rbtree and avltree
if (y->color_ == BLACK) rbnode_ = y->parent_;
else rbnode_ = BTNode<T>::nil();
avlnode_ = y->parent_;
// here we specify the new child of parent
// y is root
if (y->parent_ == BTNode<T>::nil()) root_ = x;
// y is left child
else if (y == y->parent_->lchild_) y->parent_->lchild_ = x;
// y is right child
else y->parent_->rchild_ = x;
// when y is a successor and be spiced out,
// so we replace the z's data with y's data
// and looks like z is deleted
if (y != z) z->data_ = y->data_;
delete y;
}
protected:
// transforms the configuration of the two nodes on the left into the
// configuration on the right by changing a constant number of pointers.
virtual void rotateLeft(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->rchild_;
// Turn y's left subtree into x's right subtree
x->rchild_ = y->lchild_;
if (y->lchild_ != BTNode<T>::nil()) y->lchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's left
y->lchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
// transforms the configuration of the two nodes on the right into the
// configuration on the left by changing a constant number of pointers.
virtual void rotateRight(BTNode<T>* x)
...{
// the the node is nil_, can't rotate
if (x != BTNode<T>::nil())
...{
BTNode<T> *y = x->lchild_;
// Turn y's left subtree into x's right subtree
x->lchild_ = y->rchild_;
if (y->rchild_ != BTNode<T>::nil()) y->rchild_->parent_ = x;
// Link x's parent to y
y->parent_ = x->parent_;
if (x->parent_ == BTNode<T>::nil()) root_ = y;
else if (x == x->parent_->lchild_) x->parent_->lchild_ = y;
else x->parent_->rchild_ = y;
// Put x on y's right
y->rchild_ = x;
// let y be the parent of x
x->parent_ = y;
}
BTNode<T>::nilify();
}
private:
BTNode<T>* search(BTNode<T>* x, T key)
...{
while (x != BTNode<T>::nil() && x->data_ != key)
...{
if (key < x->data_) x = search(x->lchild_, key);
else x = search(x->rchild_, key);
}
return (x->data_ == key) ? x : BTNode<T>::nil();
}
BTNode<T>* minimum(BTNode<T>* x)
...{
while (x->lchild_ != BTNode<T>::nil()) x = x->lchild_;
return x;
}
BTNode<T>* maximum(BTNode<T>* x)
...{
while (x->rchild_ != BTNode<T>::nil()) x = x->rchild_;
return x;
}
protected:
BTNode<T>* avlnode_;
BTNode<T>* rbnode_;
} ;
#endif