C++二叉查找树

原理

左节点比根节点小,右结点比根结点大

API设计

结点类:

Node<Value>
public Node* left
public Node* right
public int key
public Value value

二叉查找树:

BinaryTree<Value>
private Node* root //根节点
private int N //元素个数
public void put(Key key,Value value) //向树插入键值对
private Node* put(Node* x,Key key,Value val) //给指定树x上添加一个键值对,并返回添加后的新树
public Value get(Key key) //找寻key结点的值
private Value get(Node x,Key key) //从指定的树中找出key对应的值
public void deleteNode(Key key) //删除key结点
private Node* deleteNode(Node* x,Key key) //从指定的树中删除key结点
public int size()

代码实现

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
template <typename Value>
class Node
{
public:
    int key;
    Value value;
    Node* left;
    Node* right;
    Node() = default;
    Node(int key,Value value, Node* left, Node* right){
        this->key = key;
        this->value = value;
        this->left = left;
        this->right = right;
    }
};
template <typename Value>
class binary_tree
{
public:
    binary_tree(){
        num = 0;
        root = nullptr;
    }
    ~binary_tree(){}
    int size(){
        return num;
    }
    //向树中添加元素key-value
    void put(int key, Value value){
        root = put(root, key, value);
    }
    //向指定的树中添加元素key-value
    Node<Value>* put(Node<Value>* x, int key,Value value){
        //如果是空树
        if(x == nullptr){
            num++;
            return new Node<Value>(key, value, nullptr, nullptr);
        }
        //不是空树
        //待插入结点的key与当前节点的key值作比较
        //待插入结点的key大于当前结点的key,将待插入结点插入到当前结点的右子树
        if(key > x->key){
            x->right = put(x->right, key, value);
        }
        //待插入结点的key小于当前结点的key,将待插入结点插入到当前结点的左子树
        else if(key < x->key){
            x->left = put(x->left, key, value);
        }
        //待插入结点的key等于当前结点的key,直接改变当前结点的value即可
        else{
            x->value = value;
        }
        return x;
    }
    //查询树中指定key对应的value
    Value get(int key){
        return get(root, key);
    }
    //从指定的树x中,查找key对应的值
    Value get(Node<Value>* x, int key){
        if(x == nullptr){
            return nullptr;
        }
        //待查找的key大于当前结点的key,查找当前结点的右子树
        if(key > x->key){
            return get(x->right, key);
        }
        //待查找的key小于当前结点的key,查找当前结点的左子树
        else if(key < x->key){
           return get(x->left, key);
        }
        //待插入结点的key等于当前结点的key,返回当前结点的value
        else{
            return x->value;
        }
    }
    //删除树中key对应的value
    void deleteNode(int key){
        root = deleteNode(root, key);
    }
    //删除指定树x中的key对应的value,并返回删除后的新树
    Node<Value>* deleteNode(Node<Value>* x, int key){
        if(x == nullptr){
            return nullptr;
        }
         //待删除结点的key大于当前结点的key,查找当前结点的右子树
        if(key > x->key){
            x->right = deleteNode(x->right, key);
        }
        //待插入结点的key小于当前结点的key,查找当前结点的左子树
        else if(key < x->key){
            x->left = deleteNode(x->left, key);
        }
        //待插入结点的key等于当前结点的key,删除当前结点
        else{
            Node<Value>* newNode;
            //如果当前结点的左子树为空,直接返回当前节点的右子树
            if(x->left == nullptr){
                newNode = x->right;
                delete x;
                num--;
                return newNode;
            }
            //如果当前结点的右子树为空,直接返回当前节点的左子树
            else if(x->right == nullptr){
                newNode = x->left;
                delete x;
                num--;
                return newNode;
            }
            else{
                //找到右子树中最小的结点重建子树:最小结点即为右子树的最左结点
                Node<Value>* minNode = x->right;
                //新建n结点用于保存最左结点的父节点
                Node<Value>* n;
                //找到最左节点
                while(minNode->left != nullptr){
                    n = minNode;
                    minNode = minNode->left;
                }
                //删除最左节点
                n->left = nullptr;
                //重建子树
                minNode->right = x->right;
                minNode->left = x->right;
                delete x;
                num--;
                return minNode;
            }
        }
    }

private:
    Node<Value>* root;
    int num;
};
//测试代码
int main()
{
    binary_tree<string> bt;
    bt.put(4, "二哈");
    bt.put(1, "张三");
    bt.put(3, "李四");
    bt.put(5, "王五");
    cout << bt.size()<<endl;
    bt.put(1,"老三");
    cout << bt.get(1) << endl;
    cout << bt.size() << endl;
    cout << bt.get(3) << endl;
    cout << bt.get(4) << endl;
    cout << bt.get(5) << endl;
    bt.deleteNode(1);
    bt.deleteNode(3);
    cout << bt.size() << endl;
    return 0;
}

©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值