赞
踩
定义
二叉检索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉检索树。又称二叉搜索树,二叉排序树。
结点的实现
template<typename Key, typename E>
struct BSTNode {
typedef BSTNode<Key, E>node;
node* left;
node* right;
Key key;
E val;
BSTNode(const Key& k, const E& v,
node* l = nullptr, node* r = nullptr)
:key(k), val(v), left(l), right(r) {}
void setleft(node* t) { left = t; }
void setright(node* t) { right = t; }
};
查找
设查找的值为K,若k小于当前结点的值,则检索该节点的左子树,否则检索该节点的右子树。该过程一直持续到查找到该值或到达叶结点。若到达叶结点还未找到,则该值不在该树中。
//E为数值的数据类型,Key为键值的数据类型
E* find(const Key& k) {
return findhelp(root, k);
}
E* findhelp(node* t, const Key& k) {
//已空或为空子树,未查找到,返回空指针
if (t == nullptr) return nullptr;
//查询左子树
if (k < t->key)return findhelp(t->left, k);
//查询右子树
else if (k > t->key)return findhelp(t->right, k);
//返回键对应的值
else return &(t->val);
}
要插入一个值,首先要明确它应该被插到什么地方。递归查询它应该被插入的地方,最终达到一个叶结点或在待插入方向上没有子节点的分支结点。最后将该值插进去。
void insert(const Key& k, const E& v) { //n为结点数目 ++n; root = inserthelp(root, k, v); } node* inserthelp(node* t, const Key& k, const E& v) { //空树,直接new一个结点 if (t == nullptr)return new node(k, v); //键值大于要插入的键值,往左边插 if (k < t->key) t->setleft(inserthelp(t->left, k, v)); //否则插入右边 else t->setright(inserthelp(t->right, k, v)); //返回新的根节点 return t; }
node* deletemin(node* t) {
//直到没有左节点,返回右结点
if (t->left == nullptr)return t->right;
else {
//删除最小键值结点
t->setleft(deletemin(t->left));
//返回新的根节点
return t;
}
}
还可以根据这个性质来找到最小键值结点
node* getmin(node* t) {
//搜索到空指针,返回
if (t->left == nullptr)return t;
//一直沿着左边移动
return getmin(t->left);
}
接下来就考虑如何删除任一结点了。首先找到这一节点,
如果它没有子节点,就将它的父节点指向它的指针设为空指针。
如果它有一个子节点,那么将它的父节点指向它的指针改为指向它的子节点的指针。
如果它有两个子节点,较好的做法是从它的子树中找到一个可以替代它的值。为了保持二叉检索树的性质,我们应该选择大于等于被替换值的最小值或小于等于它的最大值。即左子树中值最大的结点或右子树中值最小的结点。由于我们在建立二叉检索树时,大于等于结点的值都在结点的右子树,故我们最好选择右子树的最小值。否则树的性质就会发生改变。
void remove(const Key& k) { root = removehelp(root, k); --n; //结点数减一 } node* removehelp(node* t, const Key& k) { //k不在树中 if (t == nullptr)return nullptr; //改变父节点的指向 if (k < t->key) t->setleft(removehelp(t->left, k)); else if (k > t->key) t->setright(removehelp(t->right, k)); //找到对应结点 else { node* temp = t; //左子树为空的情况 if (t->left == nullptr) { t = t->right; safe_delete(temp); } //右子树为空的情况 else if (t->right == nullptr) { t = t->left; safe_delete(temp); } else { //找到右子树的最小值 temp = getmin(t->right); //替换 t->val = temp->val; t->key = temp->key; //删除该节点 t->setright(deletemin(t->right)); safe_delete(temp); } } //放hi新的根节点 return t; }
#include <iostream> #include <cstdio> #include <algorithm> #define safe_delete(p) if(p){delete p;p=nullptr;} using namespace std; template<typename Key, typename E> struct BSTNode { typedef BSTNode<Key, E>node; node* left; node* right; Key key; E val; BSTNode(const Key& k, const E& v, node* l = nullptr, node* r = nullptr) :key(k), val(v), left(l), right(r) {} void setleft(node* t) { left = t; } void setright(node* t) { right = t; } }; template<typename Key, typename E> class BST { typedef BSTNode<Key, E>node; private: node* root; int n; node* inserthelp(node* t, const Key& k, const E& v) { if (t == nullptr)return new node(k, v); if (k < t->key) t->setleft(inserthelp(t->left, k, v)); else t->setright(inserthelp(t->right, k, v)); return t; } node* deletemin(node* t) { if (t->left == nullptr)return t->right; else { t->setleft(deletemin(t->left)); return t; } } node* getmin(node* t) { if (t->left == nullptr)return t; return getmin(t->left); } node* removehelp(node* t, const Key& k) { if (t == nullptr)return nullptr; if (k < t->key) t->setleft(removehelp(t->left, k)); else if (k > t->key) t->setright(removehelp(t->right, k)); else { node* temp = t; if (t->left == nullptr) { t = t->right; safe_delete(temp); } else if (t->right == nullptr) { t = t->left; safe_delete(temp); } else { temp = getmin(t->right); t->val = temp->val; t->key = temp->key; t->setright(deletemin(t->right)); safe_delete(temp); } } return t; } E* findhelp(node* t, const Key& k) { if (t == nullptr) return nullptr; if (k < t->key)return findhelp(t->left, k); else if (k > t->key)return findhelp(t->right, k); else return &(t->val); } void clearhelp(node* t) { if (t == nullptr)return; clearhelp(t->left); clearhelp(t->right); safe_delete(t); } void printhelp(node* t, int dep) { if (t == nullptr)return; printhelp(t->left, dep + 1); for (int i = 0; i < dep; ++i) putchar(' '); cout << t->key << " " << t->val << endl; printhelp(t->right, dep + 1); } public: BST() { n = 0; root = nullptr; } ~BST() { clearhelp(root); } void clear() { clearhelp(root); n = 0; root = nullptr; } void insert(const Key& k, const E& v) { ++n; root = inserthelp(root, k, v); } void remove(const Key& k) { root = removehelp(root, k); --n; } E* find(const Key& k) { return findhelp(root, k); } int size()const { return n; } void print() { if (root != nullptr) printhelp(root, 1); } }; int main(int argc, char** argv) { BST<int, int>t; int n = 5; int a, b; for (int i = 0; i < n; ++i){ scanf("%d%d",&a,&b); t.insert(a, b); } t.print(); scanf("%d",&a); int *x = t.find(a); if (x != nullptr) cout << *x << endl; safe_delete(x); t.clear(); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。