STL里的list容器里实现了许多接口,list也是我们最常用的容器之一,所以有必要熟练的运用这些接口
1.定义链表的几种方式
std::list<int> first; // 构造一个空链表
std::list<int> second (4,100); // 构造一个有四个整形结点的链表
std::list<int> third (second.begin(),second.end()); // 使用左闭右开的迭代器区间进行构造
std::list<int> fourth (third); // 调用拷贝构造
// 还可以用数组区间进行构造
int myints[] = {16,2,77,29};
std::list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
2.和迭代器有关的几个常用接口
void Testlist()
{
list<int> s1;
s1.push_back(1);
s1.push_back(2);
s1.push_back(3);
s1.push_back(4);
s1.push_back(5);
//Iterator部分的操作
//1.begin & end(配合iterator使用)
list<int>::iterator it1 = s1.begin();
cout << "正向迭代器打印:";
while (it1!=s1.end())
{
cout<< *it1 <<" ";
++it1;
}
cout << endl;
//2.rbegin & rend (配合reverse_iterator使用)
list<int>::reverse_iterator rit1 = s1.rbegin();
cout << "反向迭代器打印:";
while (rit1 != s1.rend())
{
cout<< *rit1 << " ";
++rit1;
}
cout << endl;
3.和容器容量有关的接口
cout << s1.max_size() << endl;
cout << s1.size() << endl;
max_size()返回的是容器的最大容量,等于内存最大容量/结点大小
size()返回容器当前结点的个数
empty()是判断容器是否为空,为空返回true,非空返回false;
4.一些作用容器的算法
//4.void resize (size_type n, value_type val = value_type());
cout << "resize:" << endl;
print(s1);
s1.resize(7,5);//改变list的容量,并把增加的结点插入5
print(s1);
s1.resize(10); //改变list容量,若没指定插入的值,默认为0
print(s1);
s1.resize(4);//改变list容量,若是所需容量,则删除后面的结点
print(s1);
//5.void remove (const value_type& val);
cout << "remove:" << endl;
s1.resize(10, 1);
print(s1);
s1.remove(1); //删除list里所有的指定的元素
print(s1);
/*6.void splice (iterator position, list& x);
void splice(iterator position, list& x, iterator i);
void splice(iterator position, list& x, iterator first, iterator last);*/
cout << "splice:" <<endl ;
cout << "s2.splice(s2.begin(), s1);" << endl;
list<int> s2;
print(s1); //s :2 3 4
print(s2); //s2:
s2.splice(s2.begin(), s1); //把s1链表里的值插入到时s2链表里的begin()前面,并删除s1里的数据
print(s1); //s :
print(s2); //s2:2 3 4
cout <<"s1.splice(it1, s2, s2.begin());"<< endl;
s1.push_back(10);
s1.push_back(20);
s1.push_back(30);
it1 = s1.begin();
++it1; //it1 指向 20
print(s1); //s :10 20 30
print(s2); //s2: 2 3 4
s1.splice(it1, s2, s2.begin()); //在s1链表里元素20的前面插入s2的begin()元素,并删除s2里的begin元素
print(s1); //s :10 2 20 30
print(s2); //s2 : 3 4
cout << "s2.splice(s2.begin(), s1, it1,s1.end());" << endl;
list<int>::iterator it2 = s2.begin();
++it2;
print(s1);
print(s2);
s2.splice(s2.begin(), s1, it1,s1.end()); //把s1链表里的20-30这个区间里的值插入到s2链表begin前面
print(s1);
print(s2);
//7.reverse
cout << "reverse" << endl;
print(s2);
s2.reverse(); //将链表里的元素逆序打印一遍
print(s2);
//8.sort
cout << "sort" << endl;
s2.sort(); //将链表的元素按照升序排序
print(s2);
//9.merge 合并链表
cout << "merge" << endl;
s1.sort();
s2.sort();
print(s1);
print(s2);
s1.merge(s2); //将两个有序链表合并起来,并且合并后也有序,另一个链表被删除
print(s1);
print(s2);
//10.unique
cout << "unique" << endl;
s1.push_back(10);
print(s1);
s1.sort();
s1.unique(); //删除有序链表里重复的值
print(s1);
注意:merge和unique都是对有序链表进行操作
5.对容器进行增删改的接口
//12.assign
cout << "assign" << endl;
print(s1);
int a[] = { 1, 2, 3, 4, 5 };
s1.assign(a+1 , a + 3); //重新分配链表里的内容,并重新修改其大小,注意参数是左闭右开区间。
print(s1);
//13.void resize (size_type n, value_type val = value_type());调整容器的大小,使其包含n个元素。
for (int i = 1; i<10; ++i)
s1.push_back(i);
print(s1);
s1.resize(5);
print(s1);
s1.resize(8, 100);
print(s1);
s1.resize(12);
print(s1);
//emplace操作是C++11新特性
新引入的的三个成员emlace_front、empace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部。
例子
假定d是一个Date类型的容器。
//使用三个参数的Date构造函数,在容器管理的内存空间中构造新元素。
d.emplace_back(“2016”,”05”,”26”);
//错误,push_back没有这种用法
d.push_back(“2016”,”05”,”26”);
//push_back()创建一个临时对象,然后将临时对象拷贝到容器中
d.push_back(Date(“2016”,”05”,”26”));
通过例子发现,使用C++11新特性emplace向容器中添加新元素,在容器管理的内存空间中构造新元素,与insert相比,省去了构造临时对象,减少了内存开销。
两者的区别
当调用insert时,我们将元素类型的对象传递给insert,元素的对象被拷贝到容器中,而当我们使用emplace时,我们将参数传递元素类型的构造函函数,emplace使用这些参数在容器管理的内存空间中直接构造元素。
注意:emplace函数在容器中直接构造元素,传递给emplace函数的参数必须与元素类型的构造函数相匹配。
//insert()
single element (1) | iterator insert (iterator position, const value_type& val); |
---|---|
fill (2) | void insert (iterator position, size_type n, const value_type& val); |
range (3) | template <class InputIterator> void insert (iterator position, InputIterator first, InputIterator last); |
position代表迭代器指针
val代表要插入的值
n代表插入几个val
first和last代表左闭右开的迭代器区间,可以把其他容器的值插入本容器
list<int> mylist;
list<int>::iterator it = mylist.begin();
vector<int> myvector(5, 10);
mylist.insert(it, myvector.begin(), myvector.end());
print(mylist); // 正向迭代器打印:10 10 10 10 10
其他一些比较熟悉的增删改的接口,就不演示了。
模拟stl里的list代码:github