zoukankan      html  css  js  c++  java
  • 字典树的C++实现

    此次代码使用了诸多新鲜玩意,比如自动类型推断,模板类等等,感觉真的超级好玩啊。

    自己做了一个简易的测试,程序的健壮性什么的还是比较差的,此程序留待以后进行功能补全。

    #pragma once
    #include<cstddef>
    #include<string>
    using std::strlen;
    using std::pair;
    using std::make_pair;
    
    //字典树节点
    template<int size>
    class TrieNode
    {
    public:
        TrieNode() :NodeSize(0), TerminableSize(0)
        {
            for (size_t i = 0; i < size; i++)
            {
                ChildNode[i] = NULL;
            }
        }
        ~TrieNode()
        {
            for (size_t i = 0; i < size; i++)
            {
                delete ChildNode[i];
                ChildNode[i] = NULL;
            }
        }
    
    public: //为了方便,此处将变量暴露,后续可以改进为通过接口操作
        int NodeSize;              //记录此节点子节点的个数
        int TerminableSize;        //存储以此节点结尾的字符串个数
        TrieNode* ChildNode[size]; //记录指向子节点的指针 
    };
    
    //字典树
    template < int Size, typename Type> class Trie
    {
    public:
        typedef TrieNode<Size> Node;
        typedef TrieNode<Size>* pNode;
    
    public:
        Trie() :root(new Node) {}
        ~Trie() { delete root; }
    
    public:
        template<typename itr>
        void insert(itr beg, itr end);
        void insert(const char* str);
    
        template<typename itr>
        pair<bool,int> find(itr beg, itr end);
        pair<bool,int> find(const char* str);
    
        template<typename itr>
        bool DownNodeAlone(itr beg);
    
        template<typename itr>
        bool erase(itr beg, itr end);
        bool erase(const char* str);
    
        int sizeAll(pNode);
        int sizeNodeRedundant(pNode);
    
    public:
        pNode root;
    private:
        Type index;
    };
    
    template < int Size, typename Type>
    template<typename itr>
    void Trie<Size, Type>::insert(itr beg, itr end)
    {
        pNode cur = root, pre = NULL;
    
        for (; beg != end; ++beg)
        {
            if (!cur->ChildNode[index[*beg]])
            {
                cur->ChildNode[index[*beg]] = new(Node);
                ++cur->NodeSize;
            }
            pre = cur;
            cur = cur->ChildNode[index[*beg]];
        }
        if (pre)
            ++pre->TerminableSize;
    }
    
    template < int Size, typename Type>
    void Trie<Size, Type>::insert(const char* str)
    {
        return insert(str, str + strlen(str));
    }
    
    template <int Size, typename Type>
    pair<bool, int> Trie<Size, Type>::find(const char* str)
    {
        return find(str, str + strlen(str));
    }
    
    template <int Size, typename Type>
    template<typename itr>
    pair<bool,int> Trie<Size, Type>::find(itr beg, itr end)
    {
        pNode cur = root, pre = NULL;
        pair<bool, int> res(false, 0);
        for (;beg != end;++beg)
        {
            if (!cur->ChildNode[index[*beg]])
            {
                return res;
            }
            pre = cur;
            cur = cur->ChildNode[index[*beg]];
        }
        if (pre != NULL&&pre->TerminableSize > 0)
        {
            res.first = true;
            res.second = pre->TerminableSize;
        }
        return res;
    }
    
    template <int Size, typename Type>
    template<typename itr>
    bool Trie<Size, Type>::DownNodeAlone(itr beg)
    {
        pNode cur = root;
        int terminableSum = 0;
    
        while (cur->NodeSize != 0)
        {
            terminableSum += cur->TerminableSize;
            if (cur->NodeSize > 1)
                return false;
            else
            {
                for (size_t i = 0; i < Size; i++)
                {
                    if (cur->ChildNode[i])
                    {
                        cur = cur->ChildNode[i];
                    }
                }
            }
        }
        if (terminableSum == 1)
            return true;
        else return false;
    }
    
    template <int Size, typename Type>
    template<typename itr>
    bool Trie<Size, Type>::erase(itr beg, itr end)
    {
        auto var = find(beg, end);
        if (var.first)
        {
            pNode cur = root, pre = NULL;
            for (; beg != end; ++beg)
            {
                if (DownNodeAlone(cur))
                {
                    delete cur;
                    cur = NULL;
                    return true;
                }
                pre = cur;
                cur = cur->ChildNode[index[*beg]];
            }
            if (pre->TerminableSize > 0)
                --pre->TerminableSize;
            return true;
        }
        return false;
    }
    
    template <int Size, typename Type>
    bool Trie<Size, Type>::erase(const char* str)
    {
        auto var = find(str);
        if (var.first)
        {
            erase(str, str + strlen(str));
            return true;
        }
        return false;
    }
    
    template <int Size, typename Type>
    int Trie<Size, Type>::sizeAll(pNode ptr)
    {
        if (ptr == NULL)
            return 0;
        int rev = ptr->TerminableSize;
        for (size_t i = 0; i < Size; i++)
        {
            rev += sizeAll(ptr->ChildNode[i]);
        }
        return rev;
    }
    
    template <int Size, typename Type>
    int Trie<Size, Type>::sizeNodeRedundant(pNode ptr)
    {
        if (NULL == ptr)
            return 0;
        int i, rev = 0;
        if (ptr->TerminableSize > 0)
            rev = 1;
        if (ptr->NodeSize != 0)
        {
            for (i = 0; i < Size; ++i)
            {
                rev += sizeNodeRedundant(ptr->ChildNode[i]);
            }
        }
        return rev;
    }
    
    template<int Size>
    class Index
    {
    public:
        Index() {}
        ~Index() {}
    
    public:
        int operator[](char vchar)
        {
            return (vchar - 'a') % Size;
        }
    };

    测试:

    int main(void)
    {
        {
            Trie<26, Index<26>> temp;
            temp.insert("hello");
            temp.insert("he");
            temp.insert("he");
            temp.insert("her");
            temp.insert("him");
            temp.insert("fuck");
            temp.insert("fuckyou");
            temp.insert("hupu");
            temp.insert("lady");
            temp.insert("hahah");
            temp.insert("lady");
            temp.insert("lady");
            temp.insert("lady");
    
            auto var = temp.find("lady");
            cout << "lady:" << boolalpha <<var.first <<" "<<var.second<< endl;
            var = temp.find("heihei");
            cout << "heihei:" << boolalpha << var.first << " " << var.second << endl;
    
            cout << "size:" << temp.sizeAll(temp.root) << endl;
            cout << "size of NoneRedundant:" << temp.sizeNodeRedundant(temp.root) << endl;
    
            var = temp.find("hupu");
            cout << "hupu:" << boolalpha << var.first <<" "<<var.second<< endl;
            temp.erase("hupu");
            var = temp.find("hupu");
            cout << "hupu:" << boolalpha << var.first << " " << var.second << endl;
    
            cout << "size:" << temp.sizeAll(temp.root) << endl;
            cout << "size of NoneRedundant:" << temp.sizeNodeRedundant(temp.root) << endl;
        }
    
        cin.get();
        _CrtDumpMemoryLeaks();
        return 0;
    }
  • 相关阅读:
    Node.js
    EFCore-Migrations
    C#核心语法
    C#编程总结--总目录
    PHP ServerPush
    汉字转拼音
    用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树
    Sublime Text 3 绝对神器
    多线程学习总结
    分享: 利用Readability解决网页正文提取问题
  • 原文地址:https://www.cnblogs.com/jason1990/p/4760783.html
Copyright © 2011-2022 走看看