二叉搜索树

二叉搜索树

特点:父节点比左边的大,比右边的小或者相等
包含中序,先序,后序遍历,插入,删除,搜索,前驱,后继等操作。
比较糟糕的情况下树高h = O(n)。
比较好的情况树高h = lgn。
插入,删除,搜索,最大值,最小值,前驱,后继,时间复杂度都是O(h)
遍历Θ(n)
任何基于比较的算法从n个元素的任意序列中构造一颗二叉搜索树,其最坏的情况下需要Ω(nlgn)。
特点:如果一颗二叉搜索树中的一个结点有两个孩子,那么它的后继没有左孩子,它的前驱没有右孩子。
前驱的特点:在树中比它小的最大元素。
后继的特点:在树中比它大的最小元素。
后继查找:该元素的若有右子树,那么是右子树的里的最小值,若没有右子树,那么是它最低祖先并且左孩子也是一个祖先。(即它最低祖先中那个有左孩子的祖先)因为只有有左孩子祖先才能比该元素大,否则该元素上面的祖先一直比该元素小。
三个遍历的特点:根据子树根的位置在左右子树的显示前中后来区别的。
中序:左-中-右
先序:中-左-右
后序:左-右-中
区别在于**中(子树根)**的位置
关于删除元素:
被删除的元素只有一个孩子的,删除该元素把它对应的孩子补上去,并且处理父结点关系
若有2个孩子的。
分两个情况:
一个是它的孩子刚好是它的后继,那么它孩子把它位置补上,并且安排好它原来的左孩子。
若它的孩子不是他的后继,那么它的后继要替代它的位置。先把后继的位置整理好,它的后继一定是没有左孩子的,所以它后继的右孩子替代它的后继位置,并安排好它后继的右孩子的父子关系,然后它后继替换它位置,并安排好它的左右孩子(它指代要被删的元素)
关于插入:
按照二叉树特点找一个空的位置即可。


#ifndef C11LEARN_BINARYSEARCHTREE_H
#define C11LEARN_BINARYSEARCHTREE_H
#include "../chapter10/BinaryTreeNode.h"
template<typename T>
class BinarySearchTree
{
protected:
    BinaryTreeNode<T>* root;
    int size;
public:
    BinarySearchTree();
    BinarySearchTree(const BinarySearchTree<T> & binarySearchTree);
    BinarySearchTree<T> & operator= (const BinarySearchTree<T>& binarySearchTree);
    virtual ~BinarySearchTree();
    T minimum();
    T maximum();
    void insert(T key);
    bool remove(const T& key);
    bool contains(const T& key);
    bool empty();
    int length();
    int successor(const T& key);
    int predecessor(const T& key);
    void inorder_tree_walk(void(*f)(const T& key));
    void preorder_tree_walk(void(*f)(const T& key));
    void postorder_tree_walk(void(*f)(const T& key));
    BinaryTreeNode<T>* search(const T& key);
    BinaryTreeNode<T>* successor(BinaryTreeNode<T>* node);
    BinaryTreeNode<T>* predecessor(BinaryTreeNode<T>* node);
    BinaryTreeNode<T>* get_root();
protected:
    void transplant(BinaryTreeNode<T>*replaced,BinaryTreeNode<T>*substitute);
    void insert(BinaryTreeNode<T>* node);
    void remove(BinaryTreeNode<T>* node);
    BinaryTreeNode<T>* minimum(BinaryTreeNode<T>* node);
    BinaryTreeNode<T>* maximum(BinaryTreeNode<T>* node);
    void iterative_inorder_tree_walk(void(*f)(BinaryTreeNode<T>* node));
    void inorder_tree_walk(void(*f)(const T&key),BinaryTreeNode<T>* node);
    void preorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node);
    void postorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node);
    void copy(BinaryTreeNode<T>* node);
};
template<typename T>
BinarySearchTree<T>::BinarySearchTree(){
    root = nullptr;
    size = 0;
}
template<typename T>
void BinarySearchTree<T>::copy(BinaryTreeNode<T>* node){
    if(node!= nullptr)
    {
        insert(node->key);
        if(node->left!= nullptr)
            copy(node->left);
        if(node->right!= nullptr)
            copy(node->right);
    }
}
template<typename T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T> & binarySearchTree){
    root = nullptr;
    copy(binarySearchTree.root);
}
template<typename T>
BinarySearchTree<T> & BinarySearchTree<T>::operator= (const BinarySearchTree<T>& binarySearchTree){
    if(&binarySearchTree == this) return *this;
    while (!empty())
        remove(root);
    root = nullptr;
    copy(binarySearchTree.root);
    return *this;
}
template<typename T>
BinarySearchTree<T>::~BinarySearchTree(){
    while (!empty())
        remove(root);
}
template<typename T>
void BinarySearchTree<T>::insert(const T key){
    insert(new BinaryTreeNode<T>(key));
}
template<typename T>
bool BinarySearchTree<T>::remove(const T& key){
    BinaryTreeNode<T>* current = search(key);
    if(current == nullptr)
        return false;
    remove(current);
    return true;
}
template<typename T>
bool BinarySearchTree<T>::contains(const T& key)
{
    return search(key)!= nullptr;
}
template<typename T>
int BinarySearchTree<T>::successor(const T& key){
    BinaryTreeNode<T>* current = successor(search(key));
    if(current == nullptr) throw "overflow";
    return current->key;
}
template<typename T>
int BinarySearchTree<T>::predecessor(const T& key){
    BinaryTreeNode<T>* current = predecessor(search(key));
    if(current == nullptr) throw "underflow";
    return current->key;
}
template<typename T>
void BinarySearchTree<T>::insert(BinaryTreeNode<T>* node){
    if(node == nullptr) return;
    BinaryTreeNode<T> *prev = nullptr;
    BinaryTreeNode<T>* current = root;
    while (current!= nullptr)
    {
        prev = current;
        if(node->key < current->key)
        {
            current = current->left;
        }
        else
        {
            current = current->right;
        }
    }
    node->parent = prev;
    if(prev == nullptr)
    {
        root = node;
    }
    else if(node->key<prev->key)
    {
        prev->left = node;
    }
    else
        prev->right = node;
    size++;
}
template<typename T>
void BinarySearchTree<T>::transplant(BinaryTreeNode<T>*replaced,BinaryTreeNode<T>*substitute){
    if(replaced == nullptr) return;
    if(replaced->parent == nullptr)
        root = substitute;
    else if(replaced->parent->right == replaced)
    {
        replaced->parent->right = substitute;
    }
    else{
        replaced->parent->left = substitute;
    }
    if(substitute!= nullptr)
        substitute->parent = replaced->parent;
}
template<typename T>
void BinarySearchTree<T>::remove(BinaryTreeNode<T>* node){
    if(node == nullptr) return;
    if(node->left == nullptr)
    {
        transplant(node,node->right);
    }
    else if(node->right == nullptr)
    {
        transplant(node,node->left);
    }
    else
    {
        BinaryTreeNode<T>* successor = minimum(node->right);
        if(successor->parent != node)
        {
            transplant(successor,successor->right);
            successor->right = node->right;
            successor->right->parent = successor;
        }
        transplant(node,successor);
        successor->left = node->left;
        successor->left->parent = successor;
    }
    delete node;
    size--;
}
template<typename T>
bool BinarySearchTree<T>::empty(){
    return root == nullptr;
}
template<typename T>
int BinarySearchTree<T>::length() {
    return size;
}
template<typename T>
T BinarySearchTree<T>::minimum(){
    if(empty()) throw "underflow";
    return minimum(root)->key;
}
template<typename T>
T BinarySearchTree<T>::maximum(){
    if(empty()) throw "underflow";
    return maximum(root)->key;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::minimum(BinaryTreeNode<T>* node){
    if(node == nullptr) return node;
    while (node->left!= nullptr)
        node = node->left;
    return node;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::maximum(BinaryTreeNode<T>* node){
    if(node == nullptr) return node;
    while (node->right!= nullptr)
        node = node->right;
    return node;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::search(const T& key){
    BinaryTreeNode<T>* current = root;
    while (current != nullptr && current->key != key)
    {
        if(key < current->key)
        {
            current = current->left;
        }
        else
        {
            current = current->right;
        }
    }
    return current;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::successor(BinaryTreeNode<T>* node){
    if(node == nullptr) return nullptr;
    if(node->right!= nullptr)
    {
        return minimum(node->right);
    }
    BinaryTreeNode<T>* parent = node->parent;
    while (parent!= nullptr && parent->right == node)
    {
        node = parent;
        parent =  parent->parent;
    }
    return parent;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::predecessor(BinaryTreeNode<T>* node){
    if(node == nullptr)return node;
    if(node->left != nullptr)
        return maximum(node->left);
    BinaryTreeNode<T>* parent = node->parent;
    while (parent!= nullptr && parent->left == node)
    {
        node = parent;
        parent = parent->parent;
    }
    return parent;
}
template<typename T>
void BinarySearchTree<T>::inorder_tree_walk(void(*f)(const T& key)){
    inorder_tree_walk(f,root);
}

template<typename T>
void BinarySearchTree<T>::iterative_inorder_tree_walk(void(*f)(BinaryTreeNode<T>* node)){
    BinaryTreeNode<T>* prev = nullptr;
    BinaryTreeNode<T>* current = root;
    while (current!= nullptr)
    {
        if(current->parent == prev)
        {
            (*f)(current);
            prev = current;
            if(current->left!= nullptr)
            {
                current = current->left;
            }
            else if(current->right!= nullptr)
            {
                current = current->right;
            }
            else
            {
                current = current->parent;
            }
        }
        else if(current->right!= nullptr && prev == current->left)
        {
            prev = current;
            current = current->right;
        }
        else
        {
            prev = current;
            current = current->parent;
        }
    }
}
template<typename T>
void BinarySearchTree<T>::preorder_tree_walk(void(*f)(const T& key)){
    preorder_tree_walk(f,root);
}
template<typename T>
void BinarySearchTree<T>::postorder_tree_walk(void(*f)(const T& key)){
    postorder_tree_walk(f,root);
}
template<typename T>
void BinarySearchTree<T>::inorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
    if(node!= nullptr)
    {
        if(node->left!= nullptr)
            inorder_tree_walk(f,node->left);
        (*f)(node->key);
        if(node->right!= nullptr)
            inorder_tree_walk(f,node->right);
    }
}
template<typename T>
void BinarySearchTree<T>::preorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
    if(node!= nullptr)
    {
        (*f)(node->key);
        if(node->left!= nullptr)
            preorder_tree_walk(f,node->left);
        if(node->right!= nullptr)
            preorder_tree_walk(f,node->right);
    }
}
template<typename T>
void BinarySearchTree<T>::postorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
    if(node!= nullptr)
    {
        if(node->left!= nullptr)
            postorder_tree_walk(f,node->left);
        if(node->right!= nullptr)
            postorder_tree_walk(f,node->right);
        (*f)(node->key);
    }
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::get_root(){
    return root;
}
#endif //C11LEARN_BINARYSEARCHTREE_H

测试代码

  int arr[] = {15,6,18,3,7,17,20,2,4,13,9};
    BinarySearchTree<int> binarySearchTree;
    for (int i : arr) {
        binarySearchTree.insert(i);
    }
    int min = binarySearchTree.minimum();
    cout<<min<<endl;
    int max = binarySearchTree.maximum();
    cout<<max<<endl;
    BinaryTreeNode<int> *node = binarySearchTree.search(9);
    cout<<node->parent->key<<endl;
    cout<<endl;
    binarySearchTree.inorder_tree_walk([](const int & key){cout<<key<<" ";});
    cout<<endl;
    binarySearchTree.preorder_tree_walk([](const int & key){cout<<key<<" ";});
    cout<<endl;
    binarySearchTree.postorder_tree_walk([](const int & key){cout<<key<<" ";});
    cout<<endl;

辅助类
BinaryTreeNode地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值