C++ 容器
/*
@note: 学习C++泛型编程
@date: 2017-11-16
@author: cloudren
*/
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <deque>
#include <list>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <typeinfo>
using namespace std;
template <class T>
void print(T t)
{
for(auto a:t)
cout<<a<<endl;
}
//2. 迭代器
//3. 容器
struct ContainsString;//前置声明
//vector
template <typename T=int>
void vector_test()
{
std::vector<T> v;
std::vector<T> v2(2);
std::vector<T> v3(2, 10);
std::vector<T> v4(v3);
int nArr[]={1,2,3,4,5,6,7,8,9,10};
std::vector<int> v5(nArr, nArr+10);
v3.push_back(16);
v3.push_back(17);
cout<<v3.size()<<endl; //容量大小4 自动增长
for(auto a:v3)
cout<<a<<endl;
cout<< (v.empty()?"v is empty" :"v is not empty")<<endl;
try
{
cout<< v3[6] << endl;//不抛出异常 访问越界!
cout<< v3.at(10)<<endl; //抛出异常
}
catch(std::exception e)
{
cerr << e.what() << endl;
}
v3.pop_back();//弹出尾部元素
v3.erase(v3.end()-1) ; //删除最后一个元素
v3.clear();//清除所有元素
for( auto a:v3)
cout<< a <<endl ;
//通过一个条件函数删除某个元素 用户自定义的条件返回true或者false
//eg: remove_if
std::vector<std::wstring> v6;
v6.push_back(L"Std template lib");
v6.push_back(L"The C++ Programming Language");
v6.push_back(L"Windows Internals");
v6.push_back(L"Programming Applications for Windows");
v6.push_back(L"Design Patterns");
v6.push_back(L"Effective C++");
v6.push_back(L"More Effective C++");
v6.erase(std::remove_if(v6.begin(),v6.end(),ContainsString(L"C++")), v6.end());
/*
typedef std::vector<std::wstring>::iterator ITER;
for(ITER it=v6.begin(); it != v6.end(); it++)
cout<< *it <<endl;//这里有问题 应该跟wstring有关系 需要研究下
cout<<L"111111111111111"<<endl;
*/
}
//定义筛选器 一元函数对象unary_function是什么 需要研究下
struct ContainsString:public std::unary_function<std::wstring, bool>
{
ContainsString(const std::wstring &wszMatch):m_wszMatch(wszMatch){}
bool operator() (const std::wstring &wszStringToMatch) const
{
return (wszStringToMatch.find(m_wszMatch) != -1 );
}
std::wstring m_wszMatch;
};
//deque
void deque_test()
{
deque<int> dq={1,2,3,4,5};//双向队列
dq.push_back(6);
dq.push_front(0);
//dq.pop_back();
dq.pop_front();
print(dq);
}
//list
void list_test()
{
list<int> l1;//双向链表
list<int> l2(10);
list<int> l3(10,8);
list<int> l4(l3);
int nArr[]={1,2,3,4,5,6,7,8,9};
int nArr2[]={11,12,13,14,15,16,17,18,19};
list<int> l5(nArr, nArr+9);
list<int> l6(nArr2, nArr2+9);
l5.splice(l5.begin(), l3, l3.begin(), l3.end()); //8888888888123456789
print(l5);
cout<<"====================================="<<endl;
#if 0
list<int>::iterator it=l5.end();
std::advance(it, -5);
cout<<*it<<endl;
#endif
// l5.splice(it, l3, l3.begin(), l3.end()); //12345678988888888888 (X splice的调用好像有问题!) __position is in [__first,__last).
l5.splice(l5.begin(), l3, l3.begin(), l3.end()); //12345678988888888888 (X splice的调用好像有问题!) __position is in [__first,__last).
print(l5);
cout<<"====================================="<<endl;
print(l3);
cout<<"====================================="<<endl;
cout<<l5.size()<<endl;
cout<<"====================================="<<endl;
l5.splice(l5.begin(), l6, l6.begin(), l6.end()); //12345678988888888888 (X splice的调用好像有问题!) __position is in [__first,__last).
print(l6);
print(l5);
}
//stack 先入后出
void stack_test()
{
//push pop top
stack<int> s1;//STl stack底层是以deque为默认结构的 template <class _Ty, class _Container=deque<_Ty> > class stack {...};
//s1.iterator 错误 stack不允许遍历,故其没有iterator
stack<int,list<int> > s2;
s2.push(1);
s2.push(2);
std::wcout<< s2.size() << endl;
std::wcout<< s2.top() << endl;
s2.pop();
std::wcout<< s2.top() << endl;
}
//queue FIFO
void queue_test()
{
//pop push front back
//只能访问最前或者最后元素 不允许遍历
//queue底层是以deque为默认结构的 template <class _Ty, class _Container=deque<_Ty> > class queue {...};
queue<int,list<int> > s2;
s2.push(1);
s2.push(2);
std::wcout<< s2.size() << endl;
std::wcout<< s2.front() << endl;
std::wcout<< s2.back() << endl;
//print(s2);//error 不允许遍历 错误!
s2.pop();
}
////////////////关联容器/////////////////////
struct Employee{
Employee(){}
Employee(const wstring& wszName):Name(wszName){
}
std::wstring Name;
};
struct ReverseId:public std::binary_function<int, int, bool> //三个参数 int代表key1的类型, int代表key2的类型, bool是返回值的类型
{
bool operator()(const int &key1, const int &key2) const{//运算符重载 自定义排序行为
return (key1<=key2)?false:true;
}
};
void map_test()
{
//key/value pair
//不允许有重复的key
//map存储的对象必须是具备可排序性的
/*
template <class _Kty, class _Ty, class _pr=less<_Kty>,
class _Alloc=allocator<pair<const _Kty, _Ty> >
class map{...};
默认采用less定义排序行为
可以采用自定义排序行为(仿函数)
*/
const int size = 3;
const std::pair<int, Employee> items[size]={
std::make_pair(1, Employee(L"Tom")),
std::make_pair(2, Employee(L"Jim")),
std::make_pair(3, Employee(L"John"))
};
std::map<int, Employee, ReverseId> map1(items, items+3);
map1.insert(make_pair(4, Employee(L"Cloud")));
map1.insert(make_pair(5, Employee(L"Lora")));
map1.erase(1);//key erase
std::map<int,Employee>::iterator it1=map1.begin();
map1.erase(it1);
map1.erase(map1.begin());
Employee &e = map1[2];
wcout<< e.Name<<endl;//Jim 对于wstring使用wcout进行输出!
cout<< map1.size()<<endl;
//一般的map
const std::pair<int, int> items2[5]={
std::make_pair(1,10),
std::make_pair(2,20),
std::make_pair(3,30),
std::make_pair(4,40),
std::make_pair(5,50),
};
map<int,int> map2(items2, items2+5);
map2.erase(map2.begin());//iterator
map2.erase(3);//key
std::map<int,int>::iterator it=map2.begin();
for(; it != map2.end();it++)
cout<< it->second <<endl;
//multimap 允许key重复
}
//set
class Person{
public:
Person(const std::wstring &wszName, const size_t nId):m_Name(wszName), m_Id(nId){
}
const wstring& GetName() const {return m_Name;}
const size_t GetId() const {return m_Id;}
wstring m_Name;
size_t m_Id;
};
struct PersonIdComparer:public std::binary_function<Person, Person, bool>{
bool operator()(const Person& p1, const Person &p2) const{
return (p1.GetId() < p2.GetId())?true:false;
}
};
struct PersonNameComparer:public std::binary_function<Person, Person, bool>{
bool operator()(const Person& p1, const Person &p2) const{
return (p1.GetName() < p2.GetName())?true:false;
}
};
void set_test()
{
//set关联容器 存储对象既是key也是value
//不允许有重复key
//set 存储对象必须是可排序的
/*
template <class _Kty, class _pr=less<_Kty>, class _Alloc=allocator<pair<const _Kty> >
class set{...};
默认采用less定义排序行为
可以采用自定义排序行为(仿函数)
*/
const size_t nSize=3;
const Person personArr[nSize]={
Person(L"Tom", 1),
Person(L"Tom2", 12),
Person(L"Tom3", 123)
};
std::set<Person, PersonIdComparer> ps1(personArr, personArr + nSize);
ps1.insert(Person(L"Tom4", 1234));
//std::set<Person, PersonIdComparer>::iterator it=ps1.begin();
//std::advance(it, 1);
//ps1.erase(it);
cout<<"===============================================\n";
std::set<Person, PersonIdComparer> ps2;
ps2.insert(Person(L"Apple0", 0));
ps2.insert(Person(L"Jerry", 6));
//相关算法 std::set_union std::set_intersection std::set_difference
#if 0
set<Person, PersonIdComparer> dst;
std::insert_iterator<set<Person, PersonIdComparer> > ii(dst, dst.begin());
std::set_union(ps1.begin(), ps1.end(), ps2.begin(), ps2.end(), ii, PersonIdComparer());//求并集
cout<< dst.size()<<endl;
typedef set<Person, PersonIdComparer>::iterator _MyIter;
_MyIter it2=dst.begin();
for(; it2!= dst.end(); it2++)
wcout<< it2->GetName()<<endl;
#endif
#if 0
{
std::set<Person, PersonIdComparer> ps3;
ps3.insert(Person(L"Tom2", 12));
ps3.insert(Person(L"Tom3", 123));
set<Person, PersonIdComparer> dst;
std::insert_iterator<set<Person, PersonIdComparer> > ii(dst, dst.begin());
std::set_intersection(ps1.begin(), ps1.end(), ps3.begin(), ps3.end(), ii, PersonIdComparer());//求交集
cout<< dst.size()<<endl;
typedef set<Person, PersonIdComparer>::iterator _MyIter;
_MyIter it2=dst.begin();
for(; it2!= dst.end(); it2++)
wcout<< it2->GetName()<<endl;
}
#endif
#if 0
{
std::set<Person, PersonIdComparer> ps3;
ps3.insert(Person(L"Apple0", 0));
ps3.insert(Person(L"Jerry", 6));
ps3.insert(Person(L"Tom2", 12));
ps3.insert(Person(L"Tom3", 123));
set<Person, PersonIdComparer> dst;
std::insert_iterator<set<Person, PersonIdComparer> > ii(dst, dst.begin());
std::set_difference(ps1.begin(), ps1.end(), ps3.begin(), ps3.end(), ii, PersonIdComparer());//求差集 (ps1 - ps1交ps3)
cout<< dst.size()<<endl;
typedef set<Person, PersonIdComparer>::iterator _MyIter;
_MyIter it2=dst.begin();
for(; it2!= dst.end(); it2++)
wcout<< it2->GetName()<<endl;
}
#endif
#if 1 //修改某个元素的name
typedef set<Person, PersonIdComparer>::iterator _MyIter;
_MyIter it2=ps1.find(Person(L"Tom", 1));
if( it2 != ps1.end())
{
const_cast<Person&>(*it2).m_Name=L"Tom Swifftor"; //一定要cast为对象的引用而不是对象本身
wcout << it2->m_Name << endl;
}
#endif
}
int main(void)
{
//vector_test();
//deque_test();
list_test();
//stack_test();
//queue_test();
//map_test();
//set_test();
return 0;
}
补:
list::splice函数
list::splice实现list拼接的功能。将源list的内容部分或全部元素删除,拼插入到目的list。
函数有以下三种声明:
void splice ( iterator position, list<T,Allocator>& x );
void splice ( iterator position, list<T,Allocator>& x, iterator i );
void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );
函数说明:
在list间移动元素, 将x的元素移动到目的list的指定位置,高效的将他们插入到目的list并从x中删除。
目的list的大小会增加,增加的大小为插入元素的大小。x的大小相应的会减少同样的大小。
前两个函数不会涉及到元素的创建或销毁。第三个函数会。
指向被删除元素的迭代器会失效。@param: position: 目的list的位置,用来标明 插入位置
@param: x: 源list
@param: first,last : x里需要被移动的元素的迭代器。区间为[first, last).包含first指向的元素,不包含last指向的元素。