二叉搜索树

二叉搜索树,亦称二叉查找树,二叉排序树,它满足以下性质:

  1. 可以为空树
  2. 不为空树时,若左子树存在,则左子树的所有节点的值均小于根节点的值
  3. 若右子树存在,则右子树的所有节点的值均大于根节点的值
  4. 左右子树均为二查搜索树
  5. 没有两个或两个以上的具有相同值的节点

二叉搜索树的遍历

  1. 先序遍历:先访问根节点,再访问左子树,最后访问右子树
  2. 中序遍历:先访问左子树,再访问根节点,最后访问右子树
  3. 后序遍历:先访问左子树,在访问右子树,最后访问根节点

例子:

先序遍历:abdefgc

中序遍历:debgfac

后序遍历:edgfbca

 

二叉搜索树的删除操作

二叉树删除操作主要分三种情况:

  1. 若被删节点属于叶节点,那么直接删除
  2. 若被删节点只有左子树或只有右子树,那么便删除该节点,同时将左子树或右子树移至其位置
  3. 若被删节点左子树及右子树均存在,则有两种删除方案
    • 在左子树中寻找拥有最大值节点,这时最大值节点必不拥有右子树,将该最大值节点的值赋值给被删节点,然后按方式2将最大值节点删除
    • 在右子树中寻找拥有最小值节点,这时最小值节点必不拥有左子树,将该最小值节点的值赋值给被删节点,然后按方式2将最小值节点删除

 

简单示例代码如下:

 

// Author: Waihui Zheng
// binary search tree

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>

namespace my_space {

template <typename T>
class BinarySearchTree {
    struct TreeNode {
        T value;
        TreeNode* left;
        TreeNode* right;

        TreeNode() : value(), left(NULL), right(NULL) {}
        TreeNode(const T& v) : value(v), left(NULL), right(NULL) {}
    };

public:
    BinarySearchTree() : _root(NULL) {}
    ~BinarySearchTree() {
        free_nodes(_root);
        _root = NULL;
    }

    // 递归方式调用
    void insert_recursive(const T& value) {
        insert_recursive(_root, value);
    }

    bool search_recursive(const T& value) {
        return search_recursive(_root, value);
    }

    void delete_recursive(const T& value) {
        delete_recursive(_root, value);
    }

    void inorder_recursive() {
        std::cout << "递归中序: ";
        inorder_recursive(_root);
        std::cout << std::endl;
    }

    void preorder_recursive() {
        std::cout << "递归先序: ";
        preorder_recursive(_root);
        std::cout << std::endl;
    }

    void postorder_recursive() {
        std::cout << "递归后序: ";
        postorder_recursive(_root);
        std::cout << std::endl;
    }

    // 非递归方式调用
    void insert_nonrecursive(const T& value) {
        insert_nonrecursive(_root, value);
    }

    bool search_nonrecursive(const T& value) {
        return search_nonrecursive(_root, value);
    }

    void delete_nonrecursive(const T& value) {
        delete_nonrecursive(_root, value);
    }

    void preorder_nonrecursive() {
        std::cout << "非递归先序: ";
        preorder_nonrecursive(_root);
        std::cout << std::endl;
    }

    void inorder_nonrecursive() {
        std::cout << "非递归中序: ";
        inorder_nonrecursive(_root);
        std::cout << std::endl;
    }

    void postorder_nonrecursive() {
        std::cout << "非递归后序: ";
        postorder_nonrecursive(_root);
        std::cout << std::endl;
    }

    void clear() {
        free_nodes(_root);
        _root = NULL;
    }

private:
    // 使用后序遍历,对树节点进行回收内存
    void free_nodes(TreeNode* root) {
        if (NULL == root) {
            return ;
        }

        free_nodes(root->left);
        free_nodes(root->right);

        delete root;
    }

    // 递归方式
    // 递归插入节点到相应位置,利用引用,可以直接知道节点被插入的具体位置
    void insert_recursive(TreeNode*& root, const T& value) {
        if (NULL == root) {
            root = new TreeNode(value);
        }

        if (root->value == value) {
            return ;
        }

        value < root->value ?
                insert_recursive(root->left, value) : insert_recursive(root->right, value);
    }

    bool search_recursive(TreeNode* root, const T& value) {
        if (root == NULL) {
            return false;
        }

        if (root->value == value) {
            return true;
        }

        if (value < root->value) {
            return search_recursive(root->left, value);
        } else {
            return search_recursive(root->right, value);
        }
    }

    void delete_recursive(TreeNode*& root, const T& value) {
        if (root == NULL) {
            return ;
        }

        if (value < root->value) {  // 往左边寻找
            delete_recursive(root->left, value);
        } else if (value > root->value) {   // 往右边寻找
            delete_recursive(root->right, value);
        } else {    //发现value的节点
            if (root->left == NULL && root->right == NULL) {    // 目标节点为叶节点
                delete root;
                root = NULL;    // root为引用,可以知道目标节点被谁所指
            } else if (root->left == NULL) {    // 目标节点只有右子树
                TreeNode* p = root;
                root = root->right;
                delete p;
            } else if (root->right == NULL) {   // 目标节点只有左子树
                TreeNode* p = root;
                root = root->left;
                delete p;
            } else {    // 目标节点左右子树均存在
                TreeNode* parent = root;
                TreeNode* cur = root->left;
                while (cur->right != NULL) {    // 寻找左子树的最大值,cur指向的节点为左子树的最大值节点,且没有右子树
                    parent = cur;
                    cur = cur->right;
                }

                root->value = cur->value;   // 左子树最大值赋给目标节点

                parent == root ?    // 两种情况,左子树根节点没有右孩子 及  左子树根节点有右孩子
                    parent->left = cur->left :
                    parent->right = cur->left;
                delete cur;
            }
        }
    }

    // 根->左子树->右子树
    void preorder_recursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        std::cout << root->value << " ";
        preorder_recursive(root->left);
        preorder_recursive(root->right);
    }

    // 左子树->根->右子树
    void inorder_recursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        inorder_recursive(root->left);
        std::cout << root->value << " ";
        inorder_recursive(root->right);
    }

    // 左子树->右子树->根
    void postorder_recursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        postorder_recursive(root->left);
        postorder_recursive(root->right);
        std::cout << root->value << " ";
    }

    // 非递归方式调用
    void insert_nonrecursive(TreeNode* root, const T& value) {
        if (root == NULL) {
            _root = new TreeNode(value);
            return ;
        }

        TreeNode* cur = root;
        while (cur != NULL) {
            if (value == cur->value) {
                return ;
            }

            if (value < cur->value) {   // 往左子树寻找
                if (cur->left != NULL) {    // 若左子树存在,继续左移
                    cur = cur->left;
                } else {    // 若左子树不存在,那么直接插入新节点
                    cur->left = new TreeNode(value);
                    return ;
                }
            } else {    // 往右子树寻找
                if (cur->right != NULL) {   // 若右子树存在,继续右移
                    cur = cur->right;
                } else {    // 若右子树不存在,那么直接插入新节点
                    cur->right = new TreeNode(value);
                    return ;
                }
            }
        }
    }

    bool search_nonrecursive(TreeNode* root, const T& value) {
        if (root == NULL) {
            return false;
        }

        TreeNode* cur = root;
        while (cur != NULL) {
            if (cur->value == value) {
                return true;
            }

            cur = value < cur->value ? cur->left : cur->right;
        }

        return false;
    }

    void delete_nonrecursive(TreeNode* root, const T& value) {
        if (root == NULL) {
            return ;
        }

        TreeNode* pre = NULL;   // 需要记录目标节点的父节点
        TreeNode* cur = root;   // cur将指向目标节点
        while (cur != NULL) {
            if (value == cur->value) {  // 找到目标节点
                if (cur->left == NULL && cur->right == NULL) {  // 目标节点为叶节点
                    if (pre == NULL) {  // 说明当前节点是根节点
                        delete cur;
                        _root = NULL;
                    } else {    // 先判断目标节点是左孩子还是右孩子
                        pre->left == cur ? pre->left = NULL : pre->right = NULL;
                        delete cur;
                    }
                } else if (cur->left != NULL && cur->right == NULL) {   // 目标节点只有左子树
                    if (pre == NULL) {  // 说明当前节点是根节点
                        _root = cur->left;
                        delete cur;
                    } else {    // 先判断目标节点是左孩子还是右孩子
                        pre->left == cur ? pre->left = cur->left : pre->right = cur->left;
                        delete cur;
                    }
                } else if (cur->left == NULL && cur->right != NULL) {   // 目标节点只有右子树
                    if (pre == NULL) {  // 说明当前节点是根节点
                        _root = cur->right;
                        delete cur;
                    } else {    // 先判断目标节点是左孩子还是右孩子
                        pre->left == cur ? pre->left = cur->right : pre->right = cur->right;
                        delete cur;
                    }
                } else {    // 目标节点左右子树均存在
                    TreeNode* extra_pre = cur;          // extra_cur指向节点的父节点
                    TreeNode* extra_cur = cur->left;    // 将指向目标节点 左子树的最大值
                    while (extra_cur->right != NULL) {  // 寻找左子树的最大值
                        extra_pre = extra_cur;
                        extra_cur = extra_cur->right;
                    }

                    cur->value = extra_cur->value;

                    if (cur == extra_pre) {     // 若 目标节点的左子树根节点没有右孩子
                        cur->left = extra_cur->left;
                    } else {
                        extra_pre->right = extra_cur->left;
                    }

                    delete extra_cur;
                }

                return ;
            }

            if (value < cur->value) {   // 往左子树寻找
                pre = cur;
                cur = cur->left;
            } else {    // 往右子树寻找
                pre = cur;
                cur = cur->right;
            }
        }
    }

    void preorder_nonrecursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        std::stack<TreeNode*> st;
        st.push(root);
        while (!st.empty()) {
            TreeNode* cur = st.top();
            st.pop();

            std::cout << cur->value << " ";

            if (cur->right != NULL) {   // 右孩子不为空,则先放右孩子
                st.push(cur->right);
            }

            if (cur->left != NULL) {    // 左孩子不为空,则放左孩子
                st.push(cur->left);
            }
        }
    }

    void inorder_nonrecursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        std::stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL) {   // 优先将左孩子依次放入栈中
            st.push(cur);
            cur = cur->left;
        }

        while (!st.empty()) {
            cur = st.top();
            st.pop();

            std::cout << cur->value << " ";

            cur = cur->right;
            while (cur != NULL) {   // 优先将左孩子依次放入栈中
                st.push(cur);
                cur = cur->left;
            }
        }
    }

    void postorder_nonrecursive(TreeNode* root) {
        if (root == NULL) {
            return ;
        }

        std::stack<TreeNode*> st;
        TreeNode* pre = NULL;
        st.push(root);
        while (!st.empty()) {
            TreeNode* cur = st.top();

            // 若当前节点为叶节点,则访问
            // 若当前节点的前驱等于当前节点的左孩子或右孩子,则访问
            if ((cur->left == NULL && cur->right == NULL) ||
                    (pre != NULL && (pre == cur->left || pre == cur->right))) {
                std::cout << cur->value << " ";
                pre = cur;
                st.pop();
            } else {
                if (cur->right != NULL) {   // 右孩子不为空,则先放右孩子
                    st.push(cur->right);
                }

                if (cur->left != NULL) {    // 左孩子不为空,则放左孩子
                    st.push(cur->left);
                }
            }
        }
    }

private:
    TreeNode* _root;
};

}

void show_recursive() {
    std::cout << "递归方式" << std::endl;

    my_space::BinarySearchTree<int> btree;
    btree.insert_recursive(7);
    btree.insert_recursive(1);
    btree.insert_recursive(3);
    btree.insert_recursive(10);
    btree.insert_recursive(2);
    btree.insert_recursive(9);
    btree.insert_recursive(4);

    btree.preorder_recursive();
    btree.inorder_recursive();
    btree.postorder_recursive();

    std::cout << "5 " << (btree.search_recursive(5) ? "存在" : "不存在") << std::endl;
    std::cout << "10 " << (btree.search_recursive(10) ? "存在" : "不存在") << std::endl;

    btree.delete_recursive(7);
    btree.inorder_recursive();
    std::cout << std::endl;

    btree.delete_recursive(3);
    btree.inorder_recursive();
    std::cout << std::endl;
    std::cout << std::endl;
}

void show_nonrecursive() {
    std::cout << "非递归方式" << std::endl;

    my_space::BinarySearchTree<int> btree;
    btree.insert_nonrecursive(7);
    btree.insert_nonrecursive(1);
    btree.insert_nonrecursive(3);
    btree.insert_nonrecursive(10);
    btree.insert_nonrecursive(2);
    btree.insert_nonrecursive(9);
    btree.insert_nonrecursive(4);

    btree.preorder_nonrecursive();
    btree.inorder_nonrecursive();
    btree.postorder_nonrecursive();

    std::cout << "5 " << (btree.search_nonrecursive(5) ? "存在" : "不存在") << std::endl;
    std::cout << "10 " << (btree.search_nonrecursive(10) ? "存在" : "不存在") << std::endl;

    btree.delete_nonrecursive(7);
    btree.inorder_recursive();
    std::cout << std::endl;

    btree.delete_nonrecursive(3);
    btree.inorder_recursive();
    std::cout << std::endl;
    std::cout << std::endl;
}

int main() {
    show_recursive();
    show_nonrecursive();
    return 0;
}

 

转载于:https://www.cnblogs.com/bugfly/p/5199477.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值