二叉检索树
- 属性:对于二叉检索树(Binary Search Tree,BST)的任何一个结点,设其值为K,则该结点左子树中任意一个结点的值都小于K;该结点右字数中任意一个结点的值都大于或等于K。
- 特点:按照中序遍历将各结点打印出来,就会得到由小到大排列的结点。
如下图所示:

- 在实现BST之前,首先需要对字典进行定义,字典提供在数据库中存储、查询、删除记录的功能。
字典的ADT:
template<typename Key, typename E>
class Dictionary{
private:
void operator =(const Dictionary&){}
Dictionary(const Dictionary&){}
public:
Dictionary(){}
virtual ~Dictionary(){}
virtual void clear() = 0;
virtual void insert(const Key& k, const E& e) = 0;
virtual E remove(const Key& k) = 0;
virtual E removeAny() = 0;
virtual E find(const Key& k) const = 0;
virtual int size() = 0;
};
template<typename Key, typename E>
class BST : public Dictionary < Key, E > {
private:
BSTNode<Key, E>* root;
int nodecount;
void clearhelp(BSTNode<Key, E>*); //清除二叉树
BSTNode<Key, E>* inserthelp(BSTNode<Key, E>*, const Key&, const E&); //插入函数
BSTNode<Key, E>* deletemin(BSTNode<Key, E>*); //删除最小结点
BSTNode<Key, E>* getmin(BSTNode<Key, E>*); //获取最小结点的值
BSTNode<Key, E>* removehelp(BSTNode<Key, E>*, const Key&); //移除函数
E findhelp(BSTNode<Key, E>*, const Key&) const; //查找函数
void printhelp(BSTNode<Key, E>*, int) const; //打印函数
public:
BST() { root = NULL; nodecount = 0; } //构造函数
~BST() { clearhelp(root); } //析构函数
//清除二叉树
void clear()
{
clearhelp(root);
root = NULL;
nodecount = 0;
}
//插入函数
void insert(const Key& k,const E& e)
{
root = inserthelp(root, k, e);
nodecount++;
}
//移除函数
E remove(const Key& k)
{
E temp = findhelp(root, k);
if (temp != NULL)
{
root = removehelp(root, k);
nodecount
}
return temp;
}
//移除所有元素
E removeAny()
{
if (root != NULL)
{
E temp = root->element;
root = removehelp(root, root->key());
nodecount
return temp;
}
else return NULL;
}
//查找元素
E find(const Key& k) const
{
return findhelp(root, k);
}
//返回当前结点的数量
int size() { return nodecount; }
//打印二叉树
void print() const
{
if (root == NULL) cout << "The BST is empty!" << endl;
else printhelp(root, 0);
}
- 查找函数:将字数的根结点及检索的值作为参数,使用递归函数实现。
template<typename Key, typename E>
E BST<Key, E>::findhelp(BSTNode<Key, E>* root, const Key& k) const
{
if (root == NULL) return NULL;
if (k < root->key())
return findhelp(root->left(), k);
else if (k > root->key())
return findhelp(root->right(), k);
else return root->element();
}
- 插入函数:要插入一个值K,首先必须要找到它应该放在书机构的什么地方。这样就会把它带到一个叶结点,或者一个在待插入的方向上没有子结点的分支结点。将这个结点即为R,接着,把一个包含K的结点作为R的子结点加上去。
从根结点到被插入结点的父节点,该路径上的各个结点都被赋予了相应的子结点指针值。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::inserthelp(BSTNode<Key, E>* root, const Key& k, const E& it)
{
if (root == NULL)
return new BSTNode<Key, E>(k, it, NULL, NULL);
if (k < root->key())
root->setLeft(inserthelp(root->left(), k, it));
else
root->setRight(inserthelp(root->right(), k, it));
return root;
}
- 由于函数调用了deletemin的缘故,在回到根结点路径上的各个结点的左指针都被重新赋予指向子树。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::deletemin(BSTNode<Key, E>* rt)
{
if (rt->left() == NULL)
{
BSTNode<Key, E>* temp = rt->right();
delete rt;
return temp->right();
}
else{
rt->setLeft(deletemin(rt->left()));
return rt;
}
}
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::getmin(BSTNode<Key, E>* rt)
{
if (rt->left() == NULL)
return rt;
else return getmin(rt->left());
}
- 如果想把一个有两个子结点的结点值删除,只需要对其右字数调用函数deletemin,并用寒素的返回值替代被删除的值。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::removehelp(BSTNode<Key, E>* rt, const Key& k)
{
if (rt == NULL)
return NULL;
else if (k < rt->key())
rt->setLeft(removehelp(rt->left(), k));
else if (k > rt->key())
rt->setRight(removehelp(rt->right(), k));
else
{
BSTNode<Key, E>* temp = rt;
if (rt->left() == NULL)
{
rt = rt->right();
delete temp;
}
else if (rt->right() == NULL)
{
rt = rt->left();
delete temp;
}
else
{
BSTNode<Key, E>* t = getmin(rt->right());
rt->setElement(t->element());
rt->setKey(t->key());
rt->setRight(deletemin(rt->right()));
delete temp;
}
}
return rt;
}
template<typename Key, typename E>
void BST<Key, E>::clearhelp(BSTNode<Key, E>* root)
{
if (root == NULL)
return;
clearhelp(root->left());
clearhelp(root->right());
delete root;
}
template<typename Key, typename E>
void BST<Key, E>::printhelp(BSTNode<Key, E>* root, int level) const
{
if (root == NULL) return;
printhelp(root->left(), level + 1);
for (int i = 0; i < level; i++)
cout << " ";
cout << root->key() << endl;
printhelp(root->right(), level + 1);
}