二叉搜索树-map/set的底层容器(C++实现)

为了聚焦于二叉搜索树算法的实现,没有采用模板支持不同数据类型,(key, value)均采用 int 数值。

二叉搜索树节点和树定义

    // 二叉树节点,(key, value) 为 (int, int)
    struct Node {
        int key = 0;
        int value = 0;
        Node *left = nullptr;
        Node *right = nullptr;

//        Node() : key(0), value(0), left(nullptr), right(nullptr) {}

        Node(int k, int v) : key(k), value(v), left(nullptr), right(nullptr) {}

        Node(Node *rhs) : key(rhs->key), value(rhs->value), left(rhs->left), right(rhs->right) {}

//        Node(int k, int v, Node *left, Node *right) : key(k), value(v), left(left), right(right) {}
    };

    // 二叉搜索树
    class BST {
    public:
        BST() : root(nullptr), count(0) {}

//        BST(Node *p, int size) : root(p), count(size) {}

        ~BST() { destory(root); }

        int size() { return count; }

        bool isEmpty() { return count == 0; }

        void insert(int k, int v);

        Node *search(int k);

        bool contain(int k);

        // 深度遍历
        void preOrder();

        void inOrder();

        void postOrder();

        // 广度遍历
        void levelOrder();

        // 最大最小值
        int maxinum();

        int mininum();

        void removeMax();

        void removeMin();

        // 删除任意节点
        void removeNode(int key);

        // floor/ceil
        Node *floor(int key);

        Node *ceil(int key);

        // 前驱/后继
        Node *predecessor(int key);

        Node *successor(int key);

    private:
        void destory(Node *p);

        Node *predecessorFromAncestor(Node *p, int key);

        Node *successorFromAncestor(Node *p, int key);

        Node *floor(Node *p, int key);

        Node *ceil(Node *p, int key);

        Node *removeNode(Node *p, int key);

        Node *maxinum(Node *p);

        Node *mininum(Node *p);

        Node *removeMax(Node *p);

        Node *removeMin(Node *p);

        Node *insert(Node *p, int k, int v);

        Node *search(Node *p, int k);

        bool contain(Node *p, int k);

        void preOrder(Node *p);

        void inOrder(Node *p);

        void postOrder(Node *p);

        void levelOrder(Node *p);


        Node *root = nullptr;
        int count = 0;
    };

插入

   void BST::insert(int k, int v) {
        root = insert(root, k, v);
    }

    Node *BST::insert(Node *node, int k, int v) {
        if (node == nullptr) {
            ++count;  // attention
            return new Node(k, v);
        }

        if (k < node->key) {
            node->left = insert(node->left, k, v);
        } else if (k > node->key) {
            node->right = insert(node->right, k, v);
        } else {
            node->value = v;
        }
        return node;
    }

查找/是否包含

    bool BST::contain(int k) {
        return contain(root, k);
    }

    bool BST::contain(Node *p, int k) {
        if (p == nullptr) {
            return false;
        }
        if (k == p->key) {
            return true;
        } else if (k < p->key) {
            return contain(p->left, k);
        } else {
            return contain(p->right, k);
        }
    }

    Node *BST::search(int k) {
        return search(root, k);
    }

    Node *BST::search(Node *p, int k) {
        if (p == nullptr) {
            return nullptr;
        }

        if (k == p->key) {
            return p;
        } else if (k < p->key) {
            return search(p->left, k);
        } else {
            return search(p->right, k);
        }
    }

深度遍历(前序、中序、后序遍历)

    void BST::preOrder() {
        preOrder(root);
    }

    void BST::inOrder() {
        inOrder(root);
    }

    void BST::postOrder() {
        postOrder(root);
    }

    void BST::preOrder(Node *p) {
        if (p) {
            std::cout << p->key << "->" << p->value << " ";
            preOrder(p->left);
            preOrder(p->right);
        }
    }

    void BST::inOrder(Node *p) {
        if (p) {
            inOrder(p->left);
            std::cout << p->key << "->" << p->value << " ";
            inOrder(p->right);
        }
    }

    void BST::postOrder(Node *p) {
        if (p) {
            postOrder(p->left);
            postOrder(p->right);
            std::cout << p->key << "->" << p->value << " ";
        }
    }

广度遍历(层序遍历)

    void BST::levelOrder() {
        levelOrder(root);
    }

    void BST::levelOrder(Node *p) {
        if (!p) {
            return;
        }
        std::queue<Node *> q;
        q.push(p);
        while (!q.empty()) {
            auto node = q.front();
            std::cout << node->key << "->" << node->value << " ";
            q.pop();

            if (node->left) {
                q.push(node->left);
            }
            if (node->right) {
                q.push(node->right);
            }
        }
    }

获取最大/最小节点

    int BST::maxinum() {
        assert(count > 0);
        Node *node = maxinum(root);
        return node->key;
    }

    int BST::mininum() {
        assert(count > 0);
        Node *node = mininum(root);
        return node->key;
    }

    Node *BST::maxinum(Node *p) {
        auto node = p;
        while (node->right) {
            node = node->right;
        }
        return node;
    }

    Node *BST::mininum(Node *p) {
        auto node = p;
        while (node->left) {
            node = node->left;
        }
        return node;
    }

删除最大/最小节点

   void BST::removeMax() {
        if (root) {
            root = removeMax(root);
        }
    }

    void BST::removeMin() {
        if (root) {
            root = removeMin(root);
        }

    }

    Node *BST::removeMax(Node *p) {
        // 迭代实现
        if (p->right == nullptr) {
            // 根节点无右子树
            Node *lnode = p->left;
            delete p;
            return lnode;
        }
        // 迭代到待删除最小节点
        auto p1 = p;
        auto p2 = p->right;
        while (p2->right) {
            p1 = p2;
            p2 = p2->right;
        }
        p1->right = p2->left;  // 最大节点可能还有左子节点
        delete p2;
        --count;
        return p;
    }

    Node *BST::removeMin(Node *p) {
        // 迭代实现
        if (p->left == nullptr) {
            // 根节点无左子树
            Node *rnode = p->right;
            delete p;
            return rnode;
        }
        // 迭代到待删除最小节点
        auto p1 = p;
        auto p2 = p->left;
        while (p2->left) {
            p1 = p2;
            p2 = p2->left;
        }
        p1->left = p2->right;  // 最小节点可能还有右子节点
        delete p2;
        --count;
        return p;
    }

前驱与后继

   // 前驱/后继
    Node *BST::predecessor(int key) {
        Node *node = search(root, key);
        // 如果key所在的节点不存在, 则key没有前驱, 返回NULL
        if (node == nullptr) {
            return nullptr;
        }

        // 如果key所在的节点左子树不为空,则其左子树的最大值为key的前驱
        if (node->left != nullptr) {
            return maxinum(node->left);
        }

        // 否则, key的前驱在从根节点到key的路径上, 在这个路径上寻找到比key小的最大值, 即为key的前驱,即key所在节点的左、右父母中搜寻
        Node *tmpNode = predecessorFromAncestor(root, key);
        if (tmpNode != nullptr) {
            return tmpNode;
        }
        return nullptr;
    }

    Node *BST::predecessorFromAncestor(Node *p, int key) {
        if (p->key == key) {
            return nullptr;
        }

        if (key < p->key) {
            // 如果当前节点大于key, 则当前节点不可能是比key小的最大值
            // 向下搜索到的结果直接返回
            return predecessorFromAncestor(p->left, key);
        } else {
            // 如果当前节点小于key, 则当前节点有可能是比key小的最大值
            // 向右继续搜索, 将结果存储到tempNode中
            Node *tmpNode = predecessorFromAncestor(p->right, key);
            if (tmpNode != nullptr) {
                // 如果tempNode为空, 则当前节点即为结果
                return tmpNode;
            } else {
                return p;
            }
        }
    }

    Node *BST::successor(int key) {
        Node *node = search(root, key);
        // 如果key所在的节点不存在, 则key没有前驱, 返回NULL
        if (node == nullptr) {
            return nullptr;
        }

        // 如果key所在的节点右子树不为空,则其右子树的最小值为key的后继
        if (node->right != nullptr) {
            return mininum(node->right);
        }

        // 否则, key的后继在从根节点到key的路径上, 在这个路径上寻找到比key大的最小值, 即为key的后继,即在key的右父母中搜寻
        Node *tmpNode = successorFromAncestor(root, key);
        if (tmpNode != nullptr) {
            return tmpNode;
        }
        return nullptr;
    }

    Node *BST::successorFromAncestor(Node *p, int key) {
        if (key == p->key) {
            return nullptr;
        }

        if (p->key < key) {
            // 如果当前节点小于key, 则当前节点不可能是比key大的最小值
            // 向下搜索到的结果直接返回
            return successorFromAncestor(p->right, key);
        } else {
            // 如果当前节点大于key, 则当前节点有可能是比key大的最小值
            // 向左继续搜索, 将结果存储到tempNode中
            Node *tmpNode = successorFromAncestor(p->left, key);
            if (tmpNode != nullptr) {
                return tmpNode;
            } else {
                // 如果tempNode为空, 则当前节点即为结果
                return p;
            }
        }
    }

删除任意节点

  // 删除任意节点
    void BST::removeNode(int key) {
        if (contain(key)) {
            root = removeNode(root, key);
        }
    }

    Node *BST::removeNode(Node *p, int key) {
        if (key < p->key) {
            p->left = removeNode(p->left, key);
            return p;
        } else if (key > p->key) {
            p->right = removeNode(p->right, key);
            return p;
        } else {
            if (p->left == nullptr) {
                auto res = p->right;
                delete p;
                return res;
            } else if (p->right == nullptr) {
                auto res = p->left;
                delete p;
                return res;
            } else {
                auto minNode = mininum(p->right);
                Node *newNode = new Node(minNode->key, minNode->value);
                newNode->left = p->left;
                newNode->right = removeMin(p->right);
                return newNode;
            }
        }
    }

floor/ceil

    // floor/ceil
    int *BST::floor(int key) {
        if (count == 0 || key < mininum()) {
            return nullptr;
        }
        Node *node = floor(root, key);
        return &(node->key);
    }

    int *BST::ceil(int key) {
        if (count == 0 || key > maxinum()) {
            return nullptr;
        }
        Node *node = ceil(root, key);
        return &(node->key);
    }

    Node *BST::floor(Node *p, int key) {
        if (p == nullptr) {
            // attention 这儿返回空的含义
            return nullptr;
        }
        // 如果p的key值和要寻找的key值相等
        // 则p本身就是key的floor节点
        if (p->key == key) {
            return p;
        }

        // 如果p的key值比要寻找的key值大
        // 则要寻找的key的floor节点一定在p的左子树中
        if (p->key > key) {
            return floor(p->left, key);
        }

        // 如果p->key < key
        // 则p有可能是key的floor节点, 也有可能不是(存在比p->key大但是小于key的其余节点)
        // 需要尝试向p的右子树寻找一下
        Node *res = floor(p->right, key);
        if (res != nullptr) {
            return res;
        }
        return p;
    }

    Node *BST::ceil(Node *p, int key) {
        if (p == nullptr) {
            // attention 这儿返回空的含义
            return nullptr;
        }
        // 如果p的key值和要寻找的key值相等
        // 则p本身就是key的ceil节点
        if (p->key == key) {
            return p;
        }

        // 如果p的key值比要寻找的key值小
        // 则要寻找的key的ceil节点一定在p的右子树中
        if (p->key < key) {
            return ceil(p->right, key);
        }

        // 如果p->key > key
        // 则p有可能是key的ceil节点, 也有可能不是(存在比p->key小但是大于key的其余节点)
        // 需要尝试向p的左子树寻找一下
        Node *res = ceil(p->left, key);
        if (res != nullptr) {
            return res;
        }
        return p;
    }

销毁节点

    void BST::destory(Node *p) {
        if (p) {
            destory(p->left);
            destory(p->right);
            delete p;
            --count;
        }
    }

 

测试

1)前驱、后继测试

   // 二叉搜索树前驱后继节点测试
    void BSTPreAndSucTest() {
        const int N = 1000;
        int arr[N];
        for (int i = 0; i < N; ++i) {
            arr[i] = i;
        }
        // [0, N-1]的数据打乱后插入二叉搜索树中
        std::random_shuffle(arr, arr + N);

        BST bst;
        for (auto v : arr) {
            bst.insert(v, v);
        }

        for (int i = 1; i < N - 1; ++i) {
            assert(bst.predecessor(i)->key == i - 1);
            assert(bst.successor(i)->key == i + 1);
        }
        return;
    }

2)floor / ceil测试

    // 二叉搜索树 floor  / ceil 测试
    void BSTFloorAndCeilTest() {
        const int N = 1000;
        int arr[N];
        for (int i = 0; i < N; ++i) {
            arr[i] = 2 * i;
        }
        // [0, 2, 4.... 2*(N-1)]的数据打乱后插入二叉搜索树中
        std::random_shuffle(arr, arr + N);

        BST bst;
        for (auto v : arr) {
            bst.insert(v, v);
        }

        for (int i = 0; i < N - 1; ++i) {
            if (i % 2 == 0) {
                // 所有偶数在二叉树中存在,则其 floor / ceil 均为其本身
                assert(bst.floor(2 * i)->key == 2 * i);
                assert(bst.ceil(2 * i)->key == 2 * i);
            } else {
                // 所有基数在二叉树中不存在,则其 floor / ceil 均为其本身 +1 或者 -1
                assert(bst.floor(i)->key == i - 1);
                assert(bst.ceil(i)->key == i + 1);
            }
        }

        bst.removeNode(2);
        assert(bst.floor(2)->key ==  0);
        assert(bst.ceil(2)->key ==  4);
        return;
    }

3)其他测试

    // 二叉搜索树测试
    void BSTTest() {
        BST bstree;
        // 插入
        bstree.insert(5, 50);
        bstree.insert(4, 40);
        bstree.insert(9, 90);
        bstree.insert(1, 10);
        bstree.insert(7, 70);
        bstree.insert(3, 30);
        bstree.insert(6, 60);
        bstree.insert(8, 80);
        bstree.insert(11, 110);
        bstree.insert(10, 100);

        // 深度遍历遍历
        bstree.preOrder();
        std::cout << std::endl;
        bstree.inOrder();
        std::cout << std::endl;
        bstree.postOrder();
        std::cout << std::endl;
        // 广度遍历
        bstree.levelOrder();
        std::cout << std::endl;

        // 搜索
        auto sv = bstree.search(10);
        bool cv = bstree.contain(10);
        sv = bstree.search(11);
        cv = bstree.contain(11);
        sv = bstree.search(8);
        cv = bstree.contain(8);
        sv = bstree.search(13);
        cv = bstree.contain(13);

        // 最大最小值
        int minnum = bstree.mininum();
        int maxnum = bstree.maxinum();
//        bstree.removeMin();
//        bstree.levelOrder();
//        std::cout << std::endl;
//        bstree.removeMax();
//        bstree.levelOrder();
//        std::cout << std::endl;

        // 删除任意节点
//        bstree.removeNode(8);
//        bstree.levelOrder();
//        std::cout << std::endl;
//        bstree.removeNode(1);
//        bstree.levelOrder();
//        std::cout << std::endl;
//        bstree.removeNode(4);
//        bstree.levelOrder();
//        std::cout << std::endl;
//        bstree.removeNode(8);
//        bstree.levelOrder();
//        std::cout << std::endl;
//        bstree.removeNode(9);
//        bstree.levelOrder();
//        std::cout << std::endl;

        // floor/ceil
        auto floorv = bstree.floor(4);
        floorv = bstree.floor(2);
        floorv = bstree.floor(0);
        floorv = bstree.floor(3);

        auto ceilv = bstree.ceil(5);
        ceilv = bstree.ceil(12);
        ceilv = bstree.ceil(2);
        ceilv = bstree.ceil(3);
        ceilv = bstree.ceil(8);

        return;
    }

参考:

https://blog.csdn.net/weixin_42983849/article/details/105622493

https://github.com/liuyubobobo/Play-with-Algorithms/blob/master/05-Binary-Search-Tree/Course%20Code%20(C%2B%2B)/Optional-05-Floor-and-Ceil-in-BST/main.cpp

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值