YList 容器适配器:给C++ STL List增加下标

C++ STL list增加下标

c++ list没有下标,利用字典树给c++list增加下标,源码如下,Trie.h中是字典树的相关操作,YList是list的相关操作,main.cpp中是测试接口的代码,没有用unit-test纯粹是因为太懒了,结尾有代码仓库地址,感兴趣的可以去看一下,部分功能还没写完,隔得时间太久了,代码都看不懂了,等后面有空再写吧。

Trie.h

/*
 * 底层使用字典树,字典树中存储key最后一位结点的pValue是list结点的迭代器
*/
#ifndef TRIE_H
#define TRIE_H
#include <vector>
#include <string>
#include <list>
#include <algorithm>
#include <QDebug>
using namespace std;

template <class T>
class Trie
{
public:
    Trie()
        : children(26),isEnd(false),pValue(),l() { }

    explicit
    Trie(const Trie& __x)
        : children(__x.children),
          isEnd(__x.isEnd),
          pValue(__x.pValue),
          l(__x.l) { }

    explicit
    Trie(const Trie&& __x)
        : children(std::move(__x.children)),
          isEnd(std::move(__x.isEnd)),
          pValue(std::move(__x.pValue)),
          l(std::move(__x.l)) { }

    //在字典树中根据key查询value
    bool search(const string& word,T& value)
    {
        if((this->children).size() && (this->l).size())
        {
            Trie<T>* node = this->searchPrefix(word);
            if(node != nullptr && node->isEnd)
            {
                value = *(node->pValue);
                return true;
            }
            return false;
        }
        return false;
    }

    //插入,输入参数为key和list结点的迭代器
    void insert(const string& word,typename list<T>::iterator value)
    {
        Trie<T> *node=this;
        for(int i=0;i<word.size();i++)
        {
            int n = word[i]-'a';
            if(node->children[n]==nullptr)
            {
                node->children[n] = new Trie<T>();
            }
            node = node->children[n];
        }
        node->isEnd = true;
        node->pValue = value;

        //list中存入字典树结点指针(结点中包含迭代器),为了实现通过迭代器删除字典树结点
        l.push_back(node);
    }

    //通过迭代器值删除字典树结点(将pValue置为空),因为l中存储的是字典树结点指针,所以l中删除了,字典树中也相应删除了
    bool deleteItem(typename list<T>::iterator value)
    {
        for(auto it=l.begin();it!=l.end();it++)
        {
            //迭代器加*代表list中的元素,*it是字典树结点指针
            if((*it)->pValue == value)
            {
                (*it)->isEnd = false;
                ((*it)->pValue)._M_node = nullptr;
                return true;
            }
        }
        return false;
    }

    //通过key删除结点
    bool deleteItem(const string& word)
    {
        Trie<T> *cnode=this;
        for(int i=0;i<word.size();i++)
        {
            int n = word[i]-'a';
            if(cnode->children[n]==nullptr)
            {
                return false;
            }
            cnode = cnode->children[n];
        }
        if(cnode->isEnd==false)
        {
            return false;
        }
        else
        {
            cnode->isEnd=false;
            //迭代器的_M_node指向list中该结点,删除时将指针置为空
            (cnode->pValue)._M_node=nullptr;
            return true;
        }
        return false;
    }

    //通过key查询迭代器,迭代器指向list中的结点
    typename list<T>::iterator findIterator(const string& word)
    {
        typename list<T>::iterator tmp;
        Trie<T> *cnode=this;
        //判断vector不为空则进行查找
        if((cnode->children).size() && (cnode->l).size())
        {
            for(int i=0;i<word.size();i++)
            {
                int n = word[i]-'a';
                if(cnode->children[n]==nullptr)
                {
                    return tmp;
                }
                cnode = cnode->children[n];
            }
            return cnode->pValue;
        }
        return tmp;
    }

    //clear
    void clear()
    {
        (this->children).clear();
        (this->l).clear();
        (this->pValue)._M_node=nullptr;
        this->isEnd=false;
    }

    //operator=
    Trie& operator=(const Trie& trie)
    {
        if(this!=&trie)
        {
            this->children = trie.children;
            this->isEnd = trie.isEnd;
            this->pValue = trie.pValue;
            this->l = trie.l;
        }
        return *this;
    }

    //operator==
    inline bool
    operator==(const Trie<T>& __x)
    {
        if(this->children == __x.children &&
                this->isEnd == __x.isEnd &&
                this->pValue == __x.pValue &&
                this->l == __x.l)
        {
            return true;
        }
        return false;
    }

    ~Trie() = default;

private:
    vector<Trie<T>*> children;
    bool isEnd;
    typename list<T>::iterator pValue;
    list<Trie<T>*> l;

    //根据key前缀查询,返回字典树结点指针,查询不到返回空
    Trie<T>* searchPrefix(const string& prefix){
        Trie<T>* node = this;
        for(int i=0;i<prefix.size();i++)
        {
            int n = prefix[i]-'a';
            if(node->children[n]==nullptr)
            {
                return nullptr;
            }
            node = node->children[n];
        }
        return node;
    }
};

#endif // TRIE_H

YList.h

#ifndef YLIST_H
#define YLIST_H
#include "Trie.h"
#include <list>
#include <iostream>

template <typename _Tp>
class YList
{
private:
    typedef list<_Tp> _YList;
    typedef Trie<_Tp> _YTrie;

public:
    //定义value_type等供算法和内部方法使用
    typedef _Tp value_type;
    typedef typename _YList::pointer pointer;
    typedef typename _YList::const_pointer const_pointer;
    typedef typename _YList::reference reference;
    typedef typename _YList::const_reference const_reference;

    //直接用list中的迭代器,迭代器中有
    //difference_type
    //iterator_category
    //value_type
    //pointer
    //reference
    //供算法使用
    typedef typename _YList::iterator iterator;
    typedef typename _YList::const_iterator const_iterator;
    typedef typename _YList::const_reverse_iterator const_reverse_iterator;
    typedef typename _YList::reverse_iterator reverse_iterator;

    typedef typename _YList::size_type size_type;
    typedef typename _YList::difference_type difference_type;
    typedef typename _YList::allocator_type allocator_type;

protected:
    _YList l;
    _YTrie t;

public:
#if __cplusplus < 201103L
    explicit
    YList(const YList& __y = YList())
    : l(__y.l), t(__y.t) { }
#else
    YList()
        : l(), t() { }

    explicit
    YList(const YList& __y)
        : l(__y.l), t(__y.t) { }

    //移动构造函数使用std::move将左值引用转为右值引用
    //移动构造函数消耗小于拷贝构造函数,在拷贝时不再是深拷贝而是浅拷贝
    //原指针将所指对象转移完后置为空,不能再被使用
    explicit
    YList(const YList&& __y)
        : l(std::move(__y.l)), t(std::move(__y.t)) { }
#endif

    //插入key和value
    void
    push_back(const string& word,const value_type& __x)
    {
        l.push_back(__x);
        iterator __tmp = l.end();
        t.insert(word,--(__tmp));
    }

    //通过key删除
    void
    erase(const string& word)
    {
        iterator __tmp = t.findIterator(word);
        if(__tmp._M_node!=nullptr)
        {
            l.erase(__tmp);
            t.deleteItem(word);
        }
    }

    //删除最后一元素
    void
    pop_back()
    {
        //先获取最后一个元素的迭代器,再调用list删除,不然会拿错
        iterator __tmp = l.end();
        //end是最后一个元素后一个迭代器,所以往前走一步
        t.deleteItem(--(__tmp));
        l.pop_back();
    }

    void print()
    {
        for(typename _YList::iterator it = l.begin();it!=l.end();it++)
        {
            std::cout<<*it<<std::endl;
        }
    }

    void print2(const string& word)
    {
        int tmp=0;
        bool res = t.search(word,tmp);
        std::cout<<"res:"<<res<<std::endl;
        std::cout<<"t:"<<tmp<<std::endl;
    }

    //find by key
    template<typename T>
    T
    findByKey(const string& key)
    {
        T res;
        t.search(key,res);
        return res;
    }


    const_iterator
    findIByKey(const string& key) const
    {
        return const_iterator(t.findIterator(key));
    }

    iterator
    findIByKey(const string& key)
    {
        return t.findIterator(key);
    }

    //构造函数,创造n个相同的值

    //构造函数,创造长度为n的list,里面没有值

    YList&
    operator=(const YList& __x)
    {
        if(this!=&__x)
        {
            this->l=__x.l;
            this->t=__x.t;
        }
        return *this;
    }

    //list&
    //operator=(list&& __x)

    //empty
    bool
    empty() const _GLIBCXX_NOEXCEPT
    {
        return l.empty();
    }

    //size
    size_type
    size() const _GLIBCXX_NOEXCEPT
    {
        return *l.end();
    }

    //max_size
    size_type
    max_size() const _GLIBCXX_NOEXCEPT
    {
        return l.max_size();
    }

    //operator ==
    inline bool
    operator==(const YList<_Tp>& __x)
    {
        if(this->l==__x.l && this->t==__x.t)
        {
            return true;
        }
        return false;
    }

    //operator !=
    inline bool
    operator!=(const YList<_Tp>& __x)
    {
        return !(*this == __x);
    }

    iterator
    begin() _GLIBCXX_NOEXCEPT
    {
        iterator it = l.begin();
        return it;
    }

    const_iterator
    begin() const _GLIBCXX_NOEXCEPT
    {
        const_iterator it = l.begin();
        return it;
    }

    iterator
    end() _GLIBCXX_NOEXCEPT
    {
        iterator it = l.end();
        return it;
    }

    const_iterator
    end() const _GLIBCXX_NOEXCEPT
    {
        const_iterator it = l.end();
        return it;
    }

#if __cplusplus >= 201103L

    const_iterator
    cbegin() const _GLIBCXX_NOEXCEPT
    {
        const_iterator it = l.begin();
        return it;
    }

    const_iterator
    cend() const _GLIBCXX_NOEXCEPT
    {
        const_iterator it = l.end();
        return it;
    }

#endif

    reference
    front() _GLIBCXX_NOEXCEPT
    {
        return *begin();
    }

    const_reference
    front() const _GLIBCXX_NOEXCEPT
    {
        return *begin();
    }

    reference
    back() _GLIBCXX_NOEXCEPT
    {
        iterator __tmp = end();
        --__tmp;
        return *__tmp;
    }

    const_reference
    back() const _GLIBCXX_NOEXCEPT
    {
        const_iterator __tmp = end();
        --__tmp;
        return *__tmp;
    }

    //push_front

    //pop_front

    //insert

    //swap

    //clear
    void
    clear() _GLIBCXX_NOEXCEPT
    {
        l.clear();
        t.clear();
    }

    //splice

    //remove

    //operator[]

    //print 打印全部,可以选择是下标还是值

    //erase 通过迭代器删除

    ~YList() = default;
};

#endif // YLIST_H

main

#include <QCoreApplication>
#include <stack>
#include <list>
#include <string>
#include <QDebug>
#include "Trie.h"
#include "YList.h"
using namespace std;
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    stack<int> s;
    list<int> s2;
    list<int>::iterator it;


//    Trie<int> obj;
//    int test=10;
//    int *point=&test;

//    int test2=12;
//    int *point2=&test2;
//    obj.insert("aaa",10);
//    obj.insert("apple",10);
//    obj.insert("bool",12);

//    int output1,output2,output3;
//    bool res1,res2,res3;
//    res1 = obj.search("aaa",output1);
//    res2 = obj.search("apple",output2);
//    res3 = obj.search("bool",output3);
//    qDebug()<<"res1:"<<res1<<"\n output1:"<<output1;
//    qDebug()<<"res2:"<<res2<<"\n output2:"<<output2;
//    qDebug()<<"res3:"<<res3<<"\n output3:"<<output3;

//    int output4=10000;
//    bool res4 = obj.deleteItem("aaa");
//    res1 = obj.search("aaa",output4);
//    qDebug()<<"res4:"<<res4<<"\n res1:"<<res1<<"\n output4:"<<output4;

    //test push_back
    YList<int> *obj = new YList<int>();
    obj->push_back("aaa",2);
    obj->push_back("bbb",4);
    obj->push_back("ccc",6);
    obj->push_back("ddd",7);
    qDebug()<<"list:";
    obj->print();
    obj->print2("aaa");
    obj->print2("bbb");
    obj->print2("ccc");

    //test erase
    qDebug()<<"\n erase";
    obj->erase("bbb");
    obj->print();
    obj->print2("bbb");

    //test pop_back
    qDebug()<<"\n pop_back";
    obj->pop_back();
    obj->print();
    obj->print2("ddd");

    //test findByKey findIByKey
    qDebug()<<"\n find by key";
    int f = obj->findByKey<int>("aaa");
    qDebug()<<"f:"<<f;
//    list<int>::const_iterator it2 = obj->findIByKey("aaa");
    YList<int>::const_iterator it2 = obj->findIByKey("aaa");
    qDebug()<<"it2:"<<*it2;

    f = obj->findByKey<int>("ccc");
    qDebug()<<"f:"<<f;
    it2 = obj->findIByKey("ccc");
//    list<int>::iterator it9 = obj->findIByKey("ccc");
    YList<int>::iterator it9 = obj->findIByKey("ccc");
    qDebug()<<"it2:"<<*it2;
    qDebug()<<"it9:"<<*it9;
    *it9 = 9;
    f = obj->findByKey<int>("ccc");
    qDebug()<<"after it9 f:"<<f;

//    f = obj->findByKey<int>("bbb");
//    qDebug()<<"f:"<<f;
//    it2 = obj->findIByKey("bbb");
//    qDebug()<<"it2:"<<*it2;

    //test empty size max_size
    qDebug()<<"\n size";
    qDebug()<<"empty:"<<obj->empty();
    qDebug()<<"size:"<<obj->size();
    qDebug()<<"max_size:"<<obj->max_size();

    //test operator=
    YList<int> obj2;
    obj2=*obj;
    qDebug()<<"\n size";
    qDebug()<<"empty:"<<obj2.empty();
    qDebug()<<"size:"<<obj2.size();
    qDebug()<<"max_size:"<<obj2.max_size();
    obj2.print();
    obj2.print2("aaa");
    obj2.print2("bbb");
    obj2.print2("ccc");

    //test operator== !=
    qDebug()<<"\n test operator ==";
    if(*obj == obj2)
    {
        qDebug()<<"obj equal obj2";
    }
    else
    {
        qDebug()<<"onj not equal obj2";
    }

    YList<int> obj3;
    if(obj3 == obj2)
    {
        qDebug()<<"obj3 equal obj2";
    }
    else
    {
        qDebug()<<"obj3 not equal obj2";
    }

    if(obj3 != obj2)
    {
        qDebug()<<"obj3 not equal obj2";
    }

    //test clear
    qDebug()<<"\n test clear";
    obj2.clear();
    qDebug()<<"size:"<<obj2.size();
    obj2.print2("aaa");
//    obj->print();
    obj2.print();

    //test end begin front back
    qDebug()<<"\n test end begin front back";
    obj2 = *obj;
    const int test = obj2.front();
    const int test2 = obj2.back();
    qDebug()<<test;
    qDebug()<<test2;
    YList<int>::iterator Itest = obj2.begin();
    YList<int>::const_iterator Itest2 = obj2.begin();
    YList<int>::const_iterator Itest3 = obj2.cbegin();
    qDebug()<<*Itest<<*Itest2<<*Itest3;

    obj2.print();

    YList<int>::iterator Itest4 = obj2.end();
    YList<int>::const_iterator Itest5 = obj2.end();
    YList<int>::const_iterator Itest6 = obj2.cend();
    Itest4--;
    Itest5--;
    Itest6--;
    qDebug()<<*(Itest4)<<*(Itest5)<<*(Itest6);

    return a.exec();
}

Gitee仓库地址:源码地址

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值