C++二分搜索树相关问题

//二叉树的深度优先遍历即为前序中序后序遍历,因为每次前中后序遍历都需要递归到底。所以为深度
//二叉树的广度优先遍历即为层序遍历
//二叉搜索树的遍历都为O(n)
//二分搜索树的缺点之一:一组数据可能组成不同的二叉树,极端情况下可能组成一个链表,此时的深度为链表的长度,从而降低性能,改进方法:构造成一个平衡二叉树,最典型的例子为红黑树,其他的树还包括:2-3tree/AVL tree/Splay tree  /平衡二叉树和堆的结合:Treap/ trie数据结构实现字典序,和单词个数无关,只和单词的字母长度有关
//一个小作业:用trie字典树来实现一个统计文本的词频
//8数码游戏/8皇后游戏(都是树形搜索的变种)
//计算机领域其他的树:KD树/区间树/哈夫曼树
#include <iostream>
#include <queue>
#include <cassert>
using namespace std;
template<typename Key,typename Value>
class BST
{
private:
    struct Node
    {
        Key key;
        Value value;
        Node *left;
        Node *right;
        Node(Key key,Value value)
        {
            this->key=key;
            this->value=value;
            this->left=this->right=NULL;
        }
        Node(Node* node)
        {
            this->key=node->key;
            this->value=node->value;
            this->left=node->left;
            this->right=node->right;
        }
    };
    Node * root;
    int count;
    //在以node为根的二叉搜索树中插入以key和value的键值对
    Node *insert(Node *node,Key key,Value value)
    {
        if(node == NULL)
        {
            count++;
            return new Node(key,value);
        }
        if(key==node->key)
        {
            node->key=key;
        }
        else if(key>node->key)
        {
            node->right=insert(node->right,key,value);
        }
        else
        {
            node->left=insert(node->left,key,value);
        }
        return node;
    }
    
    //查看以root为根的二叉树中是否存在有key这个键存在
    bool contain(Node *node,Key key)
    {
        if(node==NULL)
            return false;
        if(key==node->key)
            return true;
        else if(key>node->key)
            return contain(node->right,key);
        else
            return contain(node->left,key);
    }
    //在以node为根的二叉搜索树中查找key所对应的value
    Value* search(Node *node,Key key)
    {
        if(node==NULL)
            return NULL;
        else if(key==node->key)
            return &(node->value);
        else if(key>node->key)
            return search(node->right,key);
        else
            return search(node->left,key);
    }
    //前序遍历
    void preOrder(Node *node)
    {
        if(node!=NULL)
        {
            cout<<node->key<<" ";
            preOrder(node->left);
            preOrder(node->right);
        }
    }
    //中序遍历
    void inOrder(Node *node)
    {
        if(node!=NULL)
        {
            inOrder(node->left);
            cout<<node->key<<" ";
            inOrder(node->right);
        }
    }
    //后序遍历
    void postOrder(Node *node)
    {
        if(node!=NULL)
        {
            postOrder(node->left);
            postOrder(node->right);
            cout<<node->key<<" ";
        }
    }
    //由于后续遍历的性质,先遍历一个结点的所有子树,然后才遍历自身,这个性质可以用与析构函数,先析构所有的子树,然后再析构自身
    void destroy(Node *node)
    {
        if(node!=NULL)
        {
            destroy(node->left);
            destroy(node->right);
            
            delete node;
            count--;
        }
    }
    //返回以node为节点的二叉树中最小的节点
    Node *mininum(Node *node)
    {
        assert(node!=NULL);
        if(node->left==NULL)
            return node;
        return mininum(node->left);
    }
    
    //返回以node为节点的二叉树中最大的节点
    Node *maxinum(Node *node)
    {
        assert(node!=NULL);
        if(node->right==NULL)
            return node;
        return maxinum(node->right);
    }
    //删除以node为根的二叉树中的最小节点
    //返回删除节点后新的二叉树的根
    Node *removeMin(Node *node)
    {
        if(node->left==NULL)
        {
            Node *rightNode=node->right;
            delete node;
            count--;
            return rightNode;
        }
        node->left=removeMin(node->left);
        return node;
    }
    
    Node *removeMax(Node*node)
    {
        if(node->right==NULL)
        {
            Node *leftNode=node->left;
            delete node;
            count--;
            return leftNode;
        }
        node->right=removeMax(node->right);
        return node;
    }
    //删除以node为根的二叉树中的key节点,首先先要找到key这个节点,然后找到key这个节点的右子树的最小节点也就是key的后继节点然后把这个节点复制一份,让这个节点的right节点等于这个把这个节点的右子树的最小值删掉后返回的节点,同理这个节点也可以是左子树的最大值,时间复杂度为O(logn)
    Node *remove(Node *node,Key key)
    {
        if(node==NULL)
            return NULL;
        if(key > node->key)
        {
            node->right=remove(node->right,key);
            return node;
        }
        else if(key < node->key)
        {
            node->left=remove(node->left,key);
            return node;
        }
        else    //key==node->key
        {
            if(node->left==NULL)
            {
                Node *rightNode=node->right;
                delete node;
                count--;
                return rightNode;
            }
            if(node->right==NULL)
            {
                Node *leftNode=node->left;
                delete node;
                count--;
                return leftNode;
            }
            else
            {// node->left!=NULL && node->right!=NULL
                Node* successor=new Node(mininum(node->right));
                count++;
                successor->right=removeMin(node->right);
                successor->left=node->left;
                delete node;
                count--;
                return successor;
            }
        }
    }
public:
    BST()
    {
        root=NULL;
        count=0;
    }
    ~BST()
    {
        destroy(root);
    }
    int size()
    {
        return count;
    }
    bool IsEmpty()
    {
        return count==0;
    }
    //递归查找,然后插入
    void insert(Key key,Value value)
    {
        root=insert(root,key,value);
    }
    bool contain(Key key)
    {
        return contain(root,key);
    }
    Value* search(Key key)
    {
        return search(root,key);
    }
    void preOrder()
    {
        preOrder(root);
    }
    void inOrder()
    {
        inOrder(root);
    }
    void postOrder()
    {
        postOrder(root);
    }
    //二叉搜索树的层序遍历需要用到队列这个数据结构,每次队列不为NULL的时候,把front元素拿出打印,随后把其左孩子和右孩子进行入队
    void levelOrder()
    {
        queue<Node*> q;
        q.push(root);
        while(!q.empty())
        {
            Node *node=q.front();
            q.pop();
            cout<<node->key<<" ";
            if(node->left!=NULL)
            {
                q.push(node->left);
            }
            if(node->right!=NULL)
            {
                q.push(node->right);
            }
        }
    }
    
    Key minimum()
    {
        Node *minNode=minimum(root);
        return minNode->key;
    }
    Key maxinum()
    {
        Node *maxNode=maxinum(root);
        return maxNode->key;
    }
    void removeMin()
    {
        if(root!=NULL)
            root=removeMin(root);
    }
    void removeMax()
    {
        if(root!=NULL)
            root=removeMax(root);
    }
    void remove(Key key)
    {
        root=remove(root,key);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值