C++数据结构自学代码-二叉查找树

内容:表(包括数组,链表,栈,队列)
参考文献:《数据结构与算法分析----C++语言描述(第四版)》
目的:希望各路大神指点一下
C++标准:C++11
操作系统:Ubuntu 18.04
编辑器:vs code
编译器:GCC 7.5.0
编译工具:CMake

二叉查找树(AVL)

#include <algorithm>
#include <iostream>

namespace my
{
    static const int ALLOWED_IMBALANCE = 1;
    template <typename>
    class BinarySearchTree;
}
template <typename T>
std::ostream &operator<<(std::ostream &, const my::BinarySearchTree<T> &); //要先声明运算符重载
namespace my
{
    template <typename T>
    class BinarySearchTree
    {
        //要将模板函数声明为友元, 则必须在函数名后面加上类型<T>, 不然会报错
        friend std::ostream &operator<<<T>(std::ostream &, const BinarySearchTree<T> &);

    public:
        BinarySearchTree() : root(nullptr) {}
        BinarySearchTree(const BinarySearchTree &rhs) : root(clone(rhs.root)) {}
        BinarySearchTree(BinarySearchTree &&rhs) : root(rhs.root) { rhs.root = nullptr; }
        BinarySearchTree &operator=(const BinarySearchTree &);
        BinarySearchTree &operator=(BinarySearchTree &&);
        ~BinarySearchTree() { clear(); }
        const T &find_max() const { return find_max(root)->data; }
        const T &find_min() const { return find_min(root)->data; }
        bool contains(const T &x) const { return contains(x, root); }
        bool empty() const { return root == nullptr; }
        void clear() { clear(root); }
        void insert(const T &x) { insert(x, root); }
        void insert(T &&x) { insert(x, root); }
        void remove(const T &x) { remove(x, root); }

    private:
        struct TreeNode
        {
            T data;
            TreeNode *left;
            TreeNode *right;
            int height;
            TreeNode(const T &d, TreeNode *l, TreeNode *r, int h)
                : data(d), left(l), right(r), height(h) {}
            TreeNode(T &&d, TreeNode *l, TreeNode *r, int h)
                : data(std::move(d)), left(l), right(r), height(h) {}
        };
        TreeNode *root;
        void insert(const T &, TreeNode *&); //指针的引用, 可以修改指针的值
        void insert(T &&, TreeNode *&);
        int height(TreeNode *t) const { return t == nullptr ? -1 : t->height; }
        void rotate_with_left_child(TreeNode *&);
        void double_rotate_with_left_child(TreeNode *&);
        void rotate_with_right_child(TreeNode *&);
        void double_rotate_with_right_child(TreeNode *&);
        void remove(const T &, TreeNode *&);
        void balance(TreeNode *&);
        TreeNode *find_max(TreeNode *) const;
        TreeNode *find_min(TreeNode *) const;
        bool contains(const T &, TreeNode *) const;
        void clear(TreeNode *&);
        TreeNode *clone(TreeNode *t) const
        {
            if (t == nullptr)
                return nullptr;
            else
                return new TreeNode(t->data, clone(t->left), clone(t->right), t->height);
        }
        void print(TreeNode *t, std::ostream &out) const
        {
            if (t != nullptr)
            {
                print(t->left, out);
                out << t->data << " ";
                print(t->right, out);
            }
        }
    };

} // namespace my
template <typename T>
std::ostream &operator<<(std::ostream &out, const my::BinarySearchTree<T> &tree)
{
    if (tree.empty())
    {
        out << "Empty tree";
    }
    else
    {
        tree.print(tree.root, out);
    }
    out << std::endl;
}
template <typename T>
bool my::BinarySearchTree<T>::contains(const T &x, TreeNode *t) const
{
    if (t == nullptr)
        return false;
    else if (x < t->data)
        return contains(x, t->left);
    else if (t->data < x) //保证只用<, 而不用>
        return contains(x, t->right);
    else
        return true;
}

template <typename T>
typename my::BinarySearchTree<T>::TreeNode *my::BinarySearchTree<T>::find_min(
    my::BinarySearchTree<T>::TreeNode *t) const
//递归版
{
    if (t == nullptr)
        return nullptr;
    if (t->left == nullptr)
        return t;
    return find_min(t->left);
}

template <typename T>
typename my::BinarySearchTree<T>::TreeNode *my::BinarySearchTree<T>::find_max(
    my::BinarySearchTree<T>::TreeNode *t) const
{
    //循环版
    if (t != nullptr)
        while (t->right != nullptr)
        {
            t = t->right;
        }
    return t;
}

template <typename T>
void my::BinarySearchTree<T>::insert(const T &x, TreeNode *&t)
{
    if (t == nullptr)
        t = new TreeNode(x, nullptr, nullptr, 0);
    else if (x < t->data)
        insert(x, t->left);
    else if (t->data < x)
        insert(x, t->right);
    else
        ; // TODO:重复元素
    balance(t);
}

template <typename T>
void my::BinarySearchTree<T>::insert(T &&x, TreeNode *&t)
{
    if (t == nullptr)
        t = new TreeNode(std::move(x), nullptr, nullptr);
    else if (x < t->data)
        insert(std::move(x), t->left);
    else if (t->data < x)
        insert(std::move(x), t->right);
    else
        ; // TODO:重复元素
    balance(t);
}

template <typename T>
void my::BinarySearchTree<T>::balance(TreeNode *&t)
{
    if (t == nullptr)
        return;
    if (height(t->left) - height(t->right) > ALLOWED_IMBALANCE) //左边高于右边
    {
        if (height(t->left->left) >=
            height(t->left->right)) //>=而不是>, 保证p127中, 删除情况下的情形
        {
            rotate_with_left_child(t);
        }
        else
        {
            double_rotate_with_left_child(t);
        }
    }
    if (height(t->right) - height(t->left) > ALLOWED_IMBALANCE)
    {
        if (height(t->right->right) >= height(t->right->left))
        {
            rotate_with_right_child(t);
        }
        else
        {
            double_rotate_with_right_child(t);
        }
    }
    t->height = std::max(height(t->left), height(t->right)) + 1;
}

template <typename T>
void my::BinarySearchTree<T>::rotate_with_left_child(TreeNode *&t)
{
    TreeNode *k1 = t->left;
    t->left = k1->right;
    k1->right = t;
    t->height = std::max(height(t->left), height(t->right)) + 1;
    k1->height = std::max(height(k1->left), t->height) + 1;
    t = k1;
}

template <typename T>
void my::BinarySearchTree<T>::rotate_with_right_child(TreeNode *&t)
{
    TreeNode *k1 = t->right;
    t->right = k1->left;
    k1->left = t;
    t->height = std::max(height(t->left), height(t->right)) + 1;
    k1->height = std::max(height(k1->right), t->height) + 1;
    t = k1;
}

template <typename T>
void my::BinarySearchTree<T>::double_rotate_with_left_child(TreeNode *&t)
{
    rotate_with_right_child(t->left);
    rotate_with_left_child(t);
}

template <typename T>
void my::BinarySearchTree<T>::double_rotate_with_right_child(TreeNode *&t)
{
    rotate_with_left_child(t->right);
    rotate_with_right_child(t);
}

template <typename T>
void my::BinarySearchTree<T>::remove(const T &x, TreeNode *&t)
{
    if (t == nullptr) // x不在树t中
        return;
    if (x < t->data) // x在左边
        remove(x, t->left);
    else if (t->data < x) // x在右边
        remove(x, t->right);
    else if (t->left != nullptr && t->right != nullptr) //左右都是孩子
    {
        t->data = find_min(t->right)->data;
        remove(t->data, t->right);
    }
    else //左右两边至少有一个nullptr
    {
        TreeNode *old = t;
        //若左边不空, 左边顶上, 左边空的, 右边顶上, 两边都空, 直接没了
        t = (t->left != nullptr) ? t->left : t->right;
        delete old;
    }
    balance(t);
}

template <typename T>
void my::BinarySearchTree<T>::clear(TreeNode *&t)
{
    if (t != nullptr)
    {
        clear(t->left);
        clear(t->right);
        delete t;
        t = nullptr;
    }
}

using namespace std;

int main(int argc, char const *argv[])
{
    my::BinarySearchTree<int> tree;
    for (int i = 0; i != 10; ++i)
    {
        tree.insert(i);
    }
    cout << tree << endl;
    cout << "max: " << tree.find_max() << endl
         << "min: " << tree.find_min() << endl;
    if (!tree.empty() && tree.contains(5))
    {
        cout << "tree contains 5." << endl;
        tree.clear();
    }
    if (tree.empty())
        cout << "Empty tree" << endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值