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();
}