二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
以下是实现代码:
struct Node{
shared_ptr<Node> left_;
shared_ptr<Node> right_;
int value_;
Node(int v){
value_ = v;
}
};
class binary_sort_tree{
// xianxu root left right
// zhongxu left root right
// houxu left right root
public:
binary_sort_tree(){
head = nullptr;
}
bool insert(int key){
shared_ptr<Node> cur = make_shared<Node>(key);
if(!head){
head = cur;
return true;
}
shared_ptr<Node> n = find(key);
if(n){
// update data
return true;
}
insert(head, cur);
return false;
}
bool insert(shared_ptr<Node>n, shared_ptr<Node> cur){
if(!n || !cur)return false;
if(cur->value_ <= n->value_){
if(n->left_ == nullptr){
return _insert(n, cur, true);
}else{
return insert(n->left_, cur);
}
}else{
if(n->right_ == nullptr){
return _insert(n, cur, false);
}else{
return insert(n->right_, cur);
}
}
return false;
}
bool _insert(shared_ptr<Node> n, shared_ptr<Node> cur, bool left){
if(!n || !cur)
return false;
if(left){
cur->left_ = n->left_;
n->left_ = cur;
}else{
cur->right_ = n->right_;
n->right_ = cur;
}
return true;
}
bool erase(int key){
if(!head){
return false;
}
if(head->value_ == key){
head = _erase(head);
return true;
}
return erase(head, key);
}
bool erase(shared_ptr<Node> n, int key){
if(!n)return false;
if(key< n->value_ && n->left_ ){
if(n->left_->value_ == key){
n->left_ = _erase(n->left_);
return true;
}else{
return erase(n->left_, key);
}
}
else if(n->right_ && key > n->value_){
if(n->right_->value_ == key){
n->right_ = _erase(n->right_);
return true;
}else {
return erase(n->right_, key);
}
}
return false;
}
// 右子节点上升,左子树挂到右子树的左叶子节点
shared_ptr<Node> _erase(shared_ptr<Node> n){
if(!n)
return nullptr;
if(n->right_){
shared_ptr<Node> cur = n->right_;
while(cur){
if(!cur->left_)break;
cur = cur->left_;
}
cur->left_ = n->left_;
return n->right_;
}else{
return n->left_;
}
return nullptr;
}
shared_ptr<Node> find(int key){
return find(head, key);
}
shared_ptr<Node> find(shared_ptr<Node> n, int key){
if(!n)return nullptr;
if(key == n->value_)
return n;
if(key > n->value_){
return find(n->right_, key);
}else{
return find(n->left_, key);
}
}
int calc_dep(shared_ptr<Node> n){
if(!n)return 0;
if(n->left_ || n->right_){
return 1+max(calc_dep(n->left_), calc_dep(n->right_));
}
return 1;
}
void xianxu_print(shared_ptr<Node> n){
if(!n)return;
printf("%d\n", n->value_);
xianxu_print(n->left_);
xianxu_print(n->right_);
};
void zhongxu_print(shared_ptr<Node> n){
if(!n)return;
zhongxu_print(n->left_);
printf("%d\n", n->value_);
zhongxu_print(n->right_);
};
void houxu_print(shared_ptr<Node> n){
if(!n)return;
houxu_print(n->left_);
houxu_print(n->right_);
printf("%d\n", n->value_);
};
void test(){
vector<int> v{11,9,7,5,3,1,2,4,6,8,10};
for(auto it: v){
insert(it);
}
zhongxu_print(head);
printf("head: %d\n", head->value_);
printf("dep: %d\n", calc_dep(head));
erase(10);
zhongxu_print(head);
printf("head: %d\n", head->value_);
printf("dep: %d\n", calc_dep(head));
}
shared_ptr<Node> head;
};
二叉查找树在通常情况下具备O(log(n))的查询效率,但是假如如test中测试用例,生成的树倾斜度非常高。如下图
最差情况下,所有节点均不在同一层,查询效率会降低到O(n)。
所以,朴素的二叉查找树一般不直接使用,而是结合一些解决平衡的方法,用以效率优化。