STL中list的容器使用介绍
来源:互联网 发布:子域名扫描工具 编辑:程序博客网 时间:2024/05/22 00:05
STL中list的容器使用介绍
STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用额外安装什么。它被内建在你的编译器之内。因为STL的list是一个简单的容器,所以我打算从它开始介绍STL如何使用。如果你懂得了这个概念,其他的就都没有问题了。另外,list容器是相当简单的,我们会看到这一点。
STL容器可以保存对象,内建对象和类对象。它们会安全的保存对象,并定义我们能够操作的这个对象的接口。放在蛋架上的鸡蛋不会滚到桌上。它们很安全。因此,在STL容器中的对象也很安全。
STL算法是标准算法,我们可以把它们应用在那些容器中的对象上。这些算法都有很著名的执行特性。它们可以给对象排序,删除它们,给它们记数,比较,找出特殊的对象,把它们合并到另一个容器中,以及执行其他有用的操作。
STL iterator就象是容器中指向对象的指针。STL的算法使用iterator在容器上进行操作。Iterator设置算法的边界 ,容器的长度,和其他一些事情。举个例子,有些iterator仅让算法读元素,有一些让算法写元素,有一些则两者都行。 Iterator也决定在容器中处理的方向。
你可以通过调用容器的成员函数begin()来得到一个指向一个容器起始位置的iterator。你可以调用一个容器的 end() 函数来得到过去的最后一个值(就是处理停在那的那个值)。
这就是STL所有的东西,容器、算法、和允许算法工作在容器中的元素上的iterator。 算法以合适、标准的方法操作对象,并可通过iterator得到容器精确的长度。一旦做了这些,它们就在也不会“跑出边界”。 还有一些其他的对这些核心组件类型有功能性增强的组件,例如函数对象。我们将会看到有关这些的例子,现在 ,我们先来看一看STL的list。
STL中的list就是一双向链表, list将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢
文中所用到两个list对象list_c1, list_c2分别有元素list_c1(10,20,30) list_c2(40,50,60)。还有一个list<int>::iterator citer用来指向list_c1或list_c2元素。
list对象的声明构造():
A. list<int> list_c0; //空链表
B. list<int> list_c1(3); //建一个含三个默认值是0的元素的链表
C. list<int> list_c2(5,2); //建一个含五个元素的链表,值都是2
D. list<int> list_c4(list_c2); //建一个list_c2的copy链表
E. list<int> list_c5(list_c1.begin(),list_c1.end()); //list_c5含list_c1一个区域的元素[_First, _Last)。
如何定义一个list对象
#include <list>
int main (void)
{
list<char > cList; //声明了list<char>模板类 的一个实例
}
1. assign() 给list赋值,有两个重载:
list_c1.assign(++list_c2.begin(), list_c2.end()) //list_c1现在为(50,60)。
list_c1.assing(7,4) //list_c1中现在为7个4,list_c1(4,4,4,4,4,4,4)。
2. back() 返回最后一元素的引用:
int i=list_c1.back(); //i=30
const int i=list_c2.back(); //i=60且不可修改
3. begin()返回第一个元素的指针(iterator)
list<int>::iterator citer=list_c1.begin(); // *citer=10
list<int>::const_iterator cciter=list_c1.begin(); //*cciter=10且为const。
4. clear()删除所有元素
list_c1.clear(); //list_c1为空 list_c1.size为0;
5. empty()判断是否链表为空
bool B=list_c1.empty(); //若list_c1为空B=true;否则B=false;
6. end()返回最后一个元素的下一位置的指针(list为空时end()=begin())
list<int>::iterator citer=list_c1.end(); //*(--citer)=30;
同begin()返回一个常指针,不能修改其中元素。
7. erase()删除一个元素或一个区域的元素(两个重载)
list_c1.erase(list_c1.begin()); // list_c1现为(20,30);
list_c1.erase(++list_c1.begin(),list_c1.end()); //list_c1现为(10);
erase的作用是,使作为参数的迭代器失效,并返回指向该迭代器下一参数的迭代器。
如下:
list<DotSource> ParticleSystem;
list<DotSource>::iterator pointer;
if(pointer->dead == true)
{
pointer = ParticleSystem.erase(pointer);
}
有一段关于错误使用erase的程序
#include<stdio.h>
#include<list>
using namespace std;
int main()
{
std::list<int>test_list;
std::list<int>::iterator test_list_it;
test_list.push_back(1);
test_list_it = test_list.begin();
for(;test_list_it != test_list.end();test_list_it++)
{
test_list.erase(test_list_it);
}
}
问题:该程序不能跳出循环
原因:test_list.erase(test_list_it);每次做erase时都有可能使迭代器失效,test_list_it++就发生错误了。可以参见effective stl一书。所有容器做erase操作时都有可能使迭代器失效。
改为:
for(;test_list_it != test_list.end();)
{
test_list.erase(test_list_it++);
}
or
for(;test_list_it != test_list.end();)
{
std::list<int>::iterator iter_e=test_list_it++;
test_list.erase(iter_e);
}
注意:
for(; test_list_it != test_list.end(); test_list_it++;)
{
std::list<int>::iterator iter_e=test_list_it;
test_list.erase(iter_e);
}
这样任然是错误的,原因是:iter_e=test_list_it 是指针值的复制,它俩其实指向同一个位置,所以iter_e失效那么test_list_it也会失效,所以test_list_it++就会有问题
如果是:
for( ; test_list_it != test_list.end() ; )
{
std::list<int>::iterator iter_e=test_list_it++;
test_list.erase(iter_e);
}
则没有问题。
8. front() 返回第一个元素的引用:
int i=list_c1.front(); //i=10;
const int i=list_c1.front(); //i=10且不可修改。
9. insert()在指定位置插入一个或多个元素(三个重载):
list_c1.insert(++list_c1.begin(), 100); //list_c1(10,100,20,30)
list_c1.insert(list_c1.begin(), 2, 200); //list_c1(200,200,20,30);
list_c1.insert(++list_c1.begin(),list_c2.begin(),--list_c2.end()); //list_c1(10,40,50,20,30);
10. max_size()返回链表最大可能长度(size_type就是int型):
list<int>::size_type i=list_c1.max_size(); //i=1073741823
11. merge()合并两个链表并使之默认升序(也可改):
list_c2.merge(list_c1); //list_c1现为空;list_c2现为list_c2(10,20,30,40,50,60)
list_c2.merge(list_c1,greater<int>()); //同上,但list_c2现为降序
12. pop_back()删除链表尾的一个元素
list_c1.pop_back() //list_c1(10,20);
13. pop_front()删除链表头的一元素
list_c1.pop_front()//list_c1(20,30)
14. push_back()增加一元素到链表尾
list_c1.push_back(100) //list_c1(10,20,30,100)
15. push_front()增加一元素到链表头
list_c1.push_front(100) //list_c1(100,10,20,30)
16. rbegin()返回链表最后一元素的后向指针(reverse_iterator or const)
list<int>::reverse_iterator riter=list_c1.rbegin(); //*riter=30
17. rend()返回链表第一元素的下一位置的后向指针
list<int>::reverse_iterator riter=list_c1.rend(); // *(--riter)=10
18. remove()删除链表中匹配值的元素(匹配元素全部删除)
list_c1.remove(10); //list_c1(20,30)
for (list<int>::iterator i = list_c1.begin(); i != list_c1.end(); ) {
printf("remove %d \n", *i);
list_c1.remove(*i++);
}
19. remove_if()删除条件满足的元素(会遍历一遍链表)
list_c1.remove_if( is_odd<int> () ); //list_c1(10,20,30)
//is_odd自己写(表奇数)
20. resize()重新定义链表长度(两重载):
list_c1.resize(4) //list_c1(10,20,30,0)用默认值填补
list_c1.resize(4,100) //list_c1(10,20,30,100)用指定值填补
21. reverse()反转链表:
list_c1.reverse(); //list_c1(30,20,10)
22. size()返回链表中元素个数
list<int>::size_type i = list_c1.size(); //i=3
23. sort()对链表排序,默认升序(可自定义)
list_c1.sort(); //list_c1(10,20,30)
list_c1.sort(great<int>()); //list_c1(30,20,10)
24. splice()对两个链表进行结合(三个重载)
list_c1.splice(++list_c1.begin(),list_c2); //list_c1(10,40,50,60,20,30) list_c2为空 全合并
list_c1.splice(++list_c1.begin(),list_c2,++list_c2.begin()); //list_c1(10,50,20,30) ; list_c2(40,60) 指定元素合并
list_c1.splice(++list_c1.begin(),list_c2,++list_c2.begin(),list_c2.end()); //list_c1(10,50,60,20,30); list_c2(40) 指定范围合并
25. swap()交换两个链表(两个重载)
list_c1.swap(list_c2); //list_c1(40,50,60);
swap(list_c1,list_c2); //list_c1(40,50,60)
26. unique()删除相邻重复元素(断言已经排序,因为它不会删除不相邻的相同元素)
list_c1.unique(); //假设list_c1开始(-10,10,10,20,20,-10)则之后为list_c1(-10,10,20,-10)
list_c1.unique(mypred); //自定义谓词
27、用list< char >::iterator得到指向list的指针 list< char>::iterator cIterator;
for(cIterator = cList.Begin(); cIterator != cList.end(); cIterator++)
{
printf(“%c”, *cIterator);
}
输出list中的所有对象 说明:cList.Begin()和cList.end()函数返回指向list< char >::iterator的指针,由于list采用链表结构,因此它不支持随机存取,因此不能用cList.begin()+3来指向list中的第四个对象,vector和deque支持随机存取。
28、用STL的通用算法count_if ()来统计list中的元素个数
const char c(‘c’);
class IsC
{
public:
bool operator() ( char& ch )
{
return ch == c;
}
};
int numC;
numC = count_if (cList.begin(), cList.end(),IsC());//统计c的数量;
说明:count_if() 带一个函数对象的参数,函数对象是一个至少带有一个operator()方法的类函数对象被约定为STL算法调用operator时返回true或false。它们根据这个来判定这个函数。举个例子会 说的更清楚些。count_if()通过传递一个函数对象来作出比count()更加复杂的评估以确定一个对象是否应该被记数。
29、使用STL通用算法find()在list中查找对象
list<char >::iterator FindIterator;
FindIterator = find(cList.begin(), cList.end(), ‘c’);
If (FindIterator == cList.end())
{
printf(“not find the char ‘c’!”);
}
else
{
printf(“%c”, *FindIterator);
}
说明:如果没有找到指定的对象,就会返回cList.end()的值,找到了就返回一个指向对象iterator的指针。
//find操作查找等于10的元素,并返回指向该元素的迭代器,如果没有找到,返回指向集合最后一个元素的迭代器
int iSearchValue = 10;
list<int>::iterator iLocation = find(ilist.begin(), ilist.end(), iSearchValue); if (iLocation != ilist.end()) { cout << "value: " <<*iLocation;
cout << "找到元素 10" << endl; }
30、使用STL通用算法find_if()在list中查找对象 const char c(‘c’);
class c
{
public:
bool operator() ( char& ch )
{
return ch== c;
}
};
list<char>::iterator FindIterator
FindIterator = find_if (cList.begin(), cList.end(), IsC());//查找字符串c;
说明:如果没有找到指定的对象,就会返回cList.end()的值,找到了就返回一个指向对象iterator的指针。
31、使用list的成员函数sort()排序
cList.sort(); //默认升序排序
32、使用list的成员函数insert插入一个对象到list中
cList.insert(cLiset.end, ‘c’); //在list末尾插入字符‘c’
char ch[3] ={‘a’, ‘b’, ‘c’};
cList.insert(cList.end, &ch[0], & ch[3] ); //插入三个字符到list中
说明:insert()函数把一个或多个元素插入到指出的iterator位置。元素将出现在 iterator指出的位置以前。
32、如何在list中删除元素
cList.pop_front(); //删除第一个元素
cList.pop_back(); //删除最后一个元素
cList. Erase(cList.begin()); //使用iterator删除第一个元素;
cList. Erase(cList.begin(), cList.End()); //使用iterator删除所有元素;
cList.remove(‘c’); //使用remove函数删除指定的对象;
list<char>::iterator newEnd; //删除所有的’c’ ,并返回指向新的list的结尾的iterator
newEnd = cList.remove(cList.begin(), cList.end(), ‘c’);
- STL中list的容器使用介绍
- STL 中 容器 list 的使用
- STL list容器的使用
- STL List容器的使用
- STL-list容器使用
- STL--> list 双向循环链表容器 接口使用及介绍。 模拟实现 STL list容器
- STL中List容器类的使用方法
- stl中list容器的嵌套
- STL list容器的使用 C++
- STL list型容器的使用
- STL中list的使用
- STL中list的使用
- STL中list的使用:
- STL中list的使用
- STL中list的使用
- STL中list的使用
- STL中list的使用
- STL中list的使用
- 115Distinct Subsequences
- Nim Game
- 安卓点击EditText,弹出日期选择界面,选择日期,返回给EditText
- (笔记)内核之输入法框架
- asdasdasda
- STL中list的容器使用介绍
- HDU1007
- 《Exceptional c++》和《提高c++性能的编程技术》学习笔记
- 构建高可用系统的常用招数
- openCV2.4.12+vs2008+cmake配置出错及解决方案
- Android自定义ListView(二) - 可上拉加载的ListView(即具有分页功能的ListView)
- 上海居住证办理流程
- Codevs 2549 自然数和分解
- isoData算法整理 常用算法 聚类算法 kmeans算法