c++搜索二叉树的实现

搜索树特点: 右子树所有节点比跟节点大 左子树所有节点比根结点小

优点:搜索性能比普通二叉树好的多 普通二叉树无任何规律 搜索性能最好情况下可达log2n级别

缺点:插入顺序如果有问题将会使该树成为一颗最垃圾的树 性能与单链表无异

#include<iostream>
template<typename T>
struct BTreeNode
{
    T data;//这里我们是把key也当做value了 其实可以分开看
    BTreeNode<T>* left;
    BTreeNode<T>* right;
};
template<typename T>
class SearchBTree
{
public:
    SearchBTree() :root(nullptr) {}
    ~SearchBTree();
    bool InserElem(const T& data);
    void InOrderTravel();
    bool DeleteElem(const T& data);
    BTreeNode<T>* FindNextIO(const T& data);//找中序的后继结点
    BTreeNode<T>* FindPreIO(const T& data);
    BTreeNode<T>* FindPrePreO(const T& data);//找这个前序的前驱结点没有任何意义 我就不实现了
    //思路如下 先找到我们要找的结点的父节点 如果该结点是父节点的左节点 则前驱结点就是父节点
    //如果是父节点的右结点 则是递归父节点的左子节点 找到存在右子节点的左子节点后中最右的右子节点 
    BTreeNode<T>* FindNextPostO(const T& data);//思路为找到父节点 如果是父节点的右子节点 后继为父节点
    //如果是父节点的左子节点 后继为父节点的右子节点中的后序遍历的第一个结点
private:
    void InOrderTravel(BTreeNode<T>* root);
    void ReleaseNode(BTreeNode<T>* root);
    bool DeleteElem(BTreeNode<T>*& root, const T& data);
    bool InsertElem(BTreeNode<T>*& root, const T& data); 
    BTreeNode<T>* FindElem(BTreeNode<T>* root,const T& data);
private:
    BTreeNode<T>* root;
};

template<typename T>
SearchBTree<T>::~SearchBTree()
{
     ReleaseNode(root);
}

template<typename T>
bool SearchBTree<T>::InserElem(const T& data)
{
    return InsertElem(root, data);
}

template<typename T>
void SearchBTree<T>::InOrderTravel()
{
    InOrderTravel(root);
}

template<typename T>
bool SearchBTree<T>::DeleteElem(const T& data)
{
    return DeleteElem(root, data);
}

template<typename T>
BTreeNode<T>* SearchBTree<T>::FindNextIO(const T& data)
{
    //找到大的里面最小的
    BTreeNode<T>* next = nullptr;
    BTreeNode<T>* cur = root;
    while (cur != nullptr)
    {
        if (cur->data > data)
        {
            next = cur;
            cur = cur->left;
        }
        else
        {
            cur = cur->right;
        }
    }
    return next;
}

template<typename T>
BTreeNode<T>* SearchBTree<T>::FindPreIO(const T& data)
{
    //前驱为比我小的里面最大的
    BTreeNode<T>* pre = nullptr;
    BTreeNode<T>* cur = root;
    while (cur != nullptr)
    {
        if (cur->data >= data)
        {
            //不用更新任何东西直接更新cur就行
            cur = cur->left;//去往更小的地方
        }
        else if (cur->data < data)
        {
            pre = cur;
            cur = cur->right;
        }
    }
    return pre;
}

template<typename T>
void SearchBTree<T>::InOrderTravel(BTreeNode<T>* root)
{
    if (root == nullptr)return;
    InOrderTravel(root->left);
    std::cout << root->data;
    InOrderTravel(root->right);
}

template<typename T>
void SearchBTree<T>::ReleaseNode(BTreeNode<T>* root)
{
    if (root == nullptr)return;
    ReleaseNode(root->left);
    ReleaseNode(root->right);
    delete root;
}

template<typename T>
bool SearchBTree<T>::DeleteElem(BTreeNode<T>*& root, const T& data)
{
    if (root == nullptr)return false;
    //找到了应该删除的结点
    if (root->data == data)
    {
        //分三种情况 第一种 左右子节点都为空 那么直接置空就完事了
        //第二种 左为空右不为空 或者右为空左不为空 任意一个替换上来就行了
        //第三种 找到左子树中最大 或者右子树中最小然后替换即可
        if (root->left == nullptr && root->right == nullptr)
        {
            ReleaseNode(root);
            root = nullptr;
        }
        else if (root->left != nullptr && root->right != nullptr)
        {
            BTreeNode<T>* tmp = root->right;
            BTreeNode<T>* tmpparent = root;
            //找右子树中最小值
            while (tmp->left)
            {
                tmpparent = tmp;
                tmp = tmp->left;
            }
            root->data = tmp->data;
            tmpparent->left = tmp->right;//收养你的右孩子
            delete tmp;
        }
        else
        {
            auto tmp = root;
            if (root->left == nullptr)
            {
                root = root->right;
            }
            else root = root->left;
            delete tmp;
        }
        return true;
    }
    else
    {
        //没找到的话继续递归
        bool left = DeleteElem(root->left, data);
        bool right = DeleteElem(root->right, data);
        return left || right;
    }
}

template<typename T>
bool SearchBTree<T>::InsertElem(BTreeNode<T>*& root, const T& data)
{
    if (root == nullptr)//找到了应该插入的位置 我们进行插入
    {
        root = new BTreeNode<T>;
        root->data = data;
        root->left = nullptr;
        root->right = nullptr;
        return true;
    }
    bool left = false;
    bool right = false;
    if (data > root->data)
    {
        right=InsertElem(root->right,data);
    }
    else if (data < root->data)
    {
        left=InsertElem(root->left,data);
    }
    else//相同的话 我们不做处理
    {
        return false;
    }
    return left||right;
}

template<typename T>
BTreeNode<T>* SearchBTree<T>::FindElem(BTreeNode<T>* root,const T& data)
{
    if (root == nullptr)return nullptr;
    if (root->data == data)return root;
    auto left = FindElem(root->left, data);
    auto right = FindElem(root->right, data);
    return left == nullptr ? right : left;
}

测试代码

int main()
{
	SearchBTree<int>tree;
	vector<int> vec{ 1,3,5,7,6,2,4,2,3,5 };
	for (auto i : vec)
	{
		tree.InserElem(i);
	}
	auto temp = tree.FindPreIO(4);
	cout << temp->data << endl;
	temp = tree.FindNextIO(4);
	cout << temp->data<<endl;
	for (auto i : vec)
	{
		tree.DeleteElem(i);
		tree.InOrderTravel();
		cout << endl;
	}

}

测试结果

猜你喜欢

转载自blog.csdn.net/qq_16401691/article/details/128053390