C++ list类详解
转自:http://blog.csdn.net/whz_zb/article/details/6831817
双向循环链表list
list是双向循环链表,,每一个元素都知道前面一个元素和后面一个元素。在STL中,list和vector一样,是两个常被使用的容器。和vector不一样的是,list不支持对元素的任意存取。list中提供的成员函数与vector类似,不过list提供对表首元素的操作push_front、pop_front,这是vector不具备的。和vector另一点不同的是,list的迭代器不会存在失效的情况,他不像vector会保留备份空间,在超过容量额度时重新全部分配内存,导致迭代器失效;list没有备份空间的概念,出入一个元素就申请一个元素的空间,所以它的迭代器不会失效。还是举《C++之vector》中的例子:
int data[6]={3,5,7,9,2,4};
list<int> lidata(data, data+6);
lidata.push_back(6);
...
list初始化时,申请的空间大小为6,存放下了data中的6个元素,当向lidata插入第7个元素“6”时,list申请新的节点单元,插入到list链表中,数据存放结构如图1所示:
图1 list的存储结构
list每次增加一个元素,不存在重新申请内存的情况,它的成本是恒定的。而vector每当增加关键元素的时候,都需要重新申请新的更大的内存空间,会调用元素的自身的复制构造函数,存在构造成本。在销毁旧内存的时候,会调用析构函数,存在析构成本。所以在存储复杂类型和大量元素的情况下,list比vector更有优势!
List是一个双向链表,双链表既可以向前又向后链接他的元素。
List将元素按顺序储存在链表中. 与 向量(vector)相比, 它允许快速的插入和删除,但是随机访问却比较慢。
assign() 给list赋值
back() 返回最后一个元素
begin() 返回指向第一个元素的迭代器
clear() 删除所有元素
empty() 如果list是空的则返回true
end() 返回末尾的迭代器
erase() 删除一个元素
front() 返回第一个元素
get_allocator() 返回list的配置器
insert() 插入一个元素到list中
max_size() 返回list能容纳的最大元素数量
merge() 合并两个list
pop_back() 删除最后一个元素
pop_front() 删除第一个元素
push_back() 在list的末尾添加一个元素
push_front() 在list的头部添加一个元素
rbegin() 返回指向第一个元素的逆向迭代器
remove() 从list删除元素
remove_if() 按指定条件删除元素
rend() 指向list末尾的逆向迭代器
resize() 改变list的大小
reverse() 把list的元素倒转
size() 返回list中的元素个数
sort() 给list排序
splice() 合并两个list
swap() 交换两个list
unique() 删除list中重复的元素
List使用实例1
#include <iostream>
#include <list>
#include <numeric>
#include <algorithm>
using namespace std;
//创建一个list容器的实例LISTINT
typedef list<int> LISTINT;
//创建一个list容器的实例LISTCHAR
typedef list<char> LISTCHAR;
int main(int argc, char *argv[])
{
//--------------------------
//用list容器处理整型数据
//--------------------------
//用LISTINT创建一个名为listOne的list对象
LISTINT listOne;
//声明i为迭代器
LISTINT::iterator i;
//从前面向listOne容器中添加数据
listOne.push_front (2);
listOne.push_front (1);
//从后面向listOne容器中添加数据
listOne.push_back (3);
listOne.push_back (4);
//从前向后显示listOne中的数据
cout<<"listOne.begin()--- listOne.end():"<<endl;
for (i = listOne.begin(); i != listOne.end(); ++i)
cout << *i << " ";
cout << endl;
//从后向后显示listOne中的数据
LISTINT::reverse_iterator ir;
cout<<"listOne.rbegin()---listOne.rend():"<<endl;
for (ir =listOne.rbegin(); ir!=listOne.rend();ir++) {
cout << *ir << " ";
}
cout << endl;
//使用STL的accumulate(累加)算法
int result = accumulate(listOne.begin(), listOne.end(),0);
cout<<"Sum="<<result<<endl;
cout<<"------------------"<<endl;
//--------------------------
//用list容器处理字符型数据
//--------------------------
//用LISTCHAR创建一个名为listOne的list对象
LISTCHAR listTwo;
//声明i为迭代器
LISTCHAR::iterator j;
//从前面向listTwo容器中添加数据
listTwo.push_front ('A');
listTwo.push_front ('B');
//从后面向listTwo容器中添加数据
listTwo.push_back ('x');
listTwo.push_back ('y');
//从前向后显示listTwo中的数据
cout<<"listTwo.begin()---listTwo.end():"<<endl;
for (j = listTwo.begin(); j != listTwo.end(); ++j)
cout << char(*j) << " ";
cout << endl;
//使用STL的max_element算法求listTwo中的最大元素并显示
j=max_element(listTwo.begin(),listTwo.end());
cout << "The maximum element in listTwo is: "<<char(*j)<<endl;
return 0;
}
List使用实例2
list: Linked list of variables, struct or objects. Insert/remove anywhere.
Two examples are given:
- The first STL example is for data type int
- The second for a list of class instances.
They are used to show a simple example and a more complex real world application.
1. Lets start with a simple example of a program using STL for a linked list:
// Simple example uses type int
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> L;
L.push_back(0); // Insert a new element at the end
L.push_front(0); // Insert a new element at the beginning
L.insert(++L.begin(),2); // Insert "2" before position of first argument
// (Place before second argument)
L.push_back(5);
L.push_back(6);
list<int>::iterator i;
for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";
cout << endl;
return 0;
}
Compile: g++ example1.cpp
Run: ./a.out
Output: 0 2 0 5 6
2. The STL tutorials and texts seem to give simple examples which do not apply to the real world. The following example is for a doubly linked list. Since we are using a class and we are not using defined built-in C++ types we have included the following:
- To make this example more complete, a copy constructor has been included although the compiler will generate a member-wise one automatically if needed. This has the same functionality as the assignment operator (=).
- The assignment (=) operator must be specified so that sort routines can assign a new order to the members of the list.
- The "less than" (<) operator must be specified so that sort routines can determine if one class instance is "less than" another.
- The "equals to" (==) operator must be specified so that sort routines can determine if one class instance is "equals to" another.
// Standard Template Library example using a class.
#include <iostream>
#include <list>
using namespace std;
// The List STL template requires overloading operators =, == and <.
//vc2005调试没有错(红色字体部分可去掉)、可用vc6.0却报错了“'operator <<' is ambiguous”(vc6.0的加上红色字体部分)
class AAA;
ostream &operator<<(ostream &output, const AAA &aaa);
class AAA
{
friend ostream &operator<<(ostream &, const AAA &);
public:
int x;
int y;
float z;
AAA();
AAA(const AAA &);
~AAA(){};
AAA &operator=(const AAA &rhs);
int operator==(const AAA &rhs) const;
int operator<(const AAA &rhs) const;
};
AAA::AAA() // Constructor
{
x = 0;
y = 0;
z = 0;
}
AAA::AAA(const AAA ©in) // Copy constructor to handle pass by value.
{
x = copyin.x;
y = copyin.y;
z = copyin.z;
}
ostream &operator<<(ostream &output, const AAA &aaa)
{
output << aaa.x << ' ' << aaa.y << ' ' << aaa.z << endl;
return output;
}
AAA& AAA::operator=(const AAA &rhs)
{
this->x = rhs.x;
this->y = rhs.y;
this->z = rhs.z;
return *this;
}
int AAA::operator==(const AAA &rhs) const
{
if( this->x != rhs.x) return 0;
if( this->y != rhs.y) return 0;
if( this->z != rhs.z) return 0;
return 1;
}
// This function is required for built-in STL list functions like sort
int AAA::operator<(const AAA &rhs) const
{
if( this->x == rhs.x && this->y == rhs.y && this->z < rhs.z) return 1;
if( this->x == rhs.x && this->y < rhs.y) return 1;
if( this->x < rhs.x ) return 1;
return 0;
}
int main()
{
list<AAA> L;
AAA Ablob ;
Ablob.x=7;
Ablob.y=2;
Ablob.z=4.2355;
L.push_back(Ablob); // Insert a new element at the end
Ablob.x=5;
L.push_back(Ablob); // Object passed by value. Uses default member-wise
// copy constructor
Ablob.z=3.2355;
L.push_back(Ablob);
Ablob.x=3;
Ablob.y=7;
Ablob.z=7.2355;
L.push_back(Ablob);
list<AAA>::iterator i;
for(i=L.begin(); i != L.end(); ++i) cout << (*i).x << " "; // print member
cout << endl;
for(i=L.begin(); i != L.end(); ++i) cout << *i << " "; // print with overloaded operator
cout << endl;
cout << "Sorted: " << endl;
L.sort();
for(i=L.begin(); i != L.end(); ++i) cout << *i << " "; // print with overloaded operator
cout << endl;
return 0;
}
Output:
-
7 5 5 3
7 2 4.2355
5 2 4.2355
5 2 3.2355
3 7 7.2355 Sorted:
3 7 7.2355
5 2 3.2355
5 2 4.2355
7 2 4.2355
STL中list的使用:
STL中的list就是一双向链表,可高效地进行插入删除元素。现总结一下它的操作。
文中所用到两个list对象c1,c2分别有元素c1(10,20,30) c2(40,50,60)。还有一个list<int>::iterator citer用来指向c1或c2元素。
list对象的声明构造():
A. list<int>c0; //空链表
B. list<int>c1(3); //建一个含三个默认值是0的元素的链表
C. list<int>c2(5,2); //建一个含五个元素的链表,值都是2
D. list<int>c4(c2); //建一个c2的copy链表
E. list<int>c5(c1.begin(),c1.end());
//c5含c1一个区域的元素[_First, _Last)。
1. assign()分配值,有两个重载:
c1.assign(++c2.begin(), c2.end()) //c1现在为(50,60)。
c1.assing(7,4) //c1中现在为7个4,c1(4,4,4,4,4,4,4)。
2. back()返回最后一元素的引用:
int i=c1.back(); //i=30
const int i=c2.back(); //i=60且不可修改
3. begin()返回第一个元素的指针(iterator)
citer=c1.begin(); // *citer=10
list<int>::const_iterator cciter=c1.begin(); //*cciter=10且为const。
4. clear()删除所有元素
c1.clear(); //c1为空 c1.size为0;
5. empty()判断是否链表为空
bool B=c1.empty(); //若c1为空B=true;否则B=false;
6. end()返回最后一个元素的下一位置的指针(list为空时end()=begin())
citer=c1.end(); //*(--citer)=30;
同begin()返回一个常指针,不能修改其中元素。
7. erase()删除一个元素或一个区域的元素(两个重载)
c1.erase(c1.begin()); // c1现为(20,30);
c1.erase(++c1.begin(),c1.end()); // c1现为(10);
8. front() 返回第一个元素的引用:
int i=c1.front(); //i=10;
const int i=c1.front(); //i=10且不可修改。
9. insert()在指定位置插入一个或多个元素(三个重载):
c1.insert(++c1.begin(),100); //c1(10,100,20,30)
c1.insert(c1.begin(),2,200); //c1(200,200,20,30);
c1.insert(++c1.begin(),c2.begin(),--c2.end());
//c1(10,40,50,20,30);
10. max_size()返回链表最大可能长度(size_type就是int型):
list<int>::size_type i=c1.max_size(); //i=1073741823
11. merge()合并两个链表并使之默认升序(也可改):
c2.merge(c1); //c1现为空;c2现为c2(10,20,30,40,50,60)
c2.merge(c1,greater<int>()); //同上,但c2现为降序
12. pop_back()删除链表尾的一个元素
c1.pop_back() //c1(10,20);
13. pop_front()删除链表头的一元素
c1.pop_front() //c1(20,30)
14. push_back()增加一元素到链表尾
c1.push_back(100) //c1(10,20,30,100)
15. push_front()增加一元素到链表头
c1.push_front(100) //c1(100,10,20,30)
16. rbegin()返回链表最后一元素的后向指针(reverse_iterator or const)
list<int>::reverse_iterator riter=c1.rbegin(); //*riter=30
17. rend()返回链表第一元素的下一位置的后向指针
list<int>::reverse_iterator riter=c1.rend(); // *(--riter)=10
18. remove()删除链表中匹配值的元素(匹配元素全部删除)
c1.remove(10); //c1(20,30)
19. remove_if()删除条件满足的元素(会遍历一遍链表)
c1.remove_if( is_odd<int> () ); //c1(10,20,30)
//is_odd自己写(表奇数)
20. resize()重新定义链表长度(两重载):
c1.resize(4) //c1(10,20,30,0)用默认值填补
c1.resize(4,100) //c1(10,20,30,100)用指定值填补
21. reverse()反转链表:
c1.reverse(); //c1(30,20,10)
22. size()返回链表中元素个数
list<int>::size_type i=c1.size(); //i=3
23. sort()对链表排序,默认升序(可自定义)
c1.sort(); //c1(10,20,30)
c1.sort(great<int>()); //c1(30,20,10)
24. splice()对两个链表进行结合(三个重载)
c1.splice(++c1.begin(),c2);
//c1(10,40,50,60,20,30) c2为空 全合并
c1.splice(++c1.begin(),c2,++c2.begin());
//c1(10,50,20,30) ; c2(40,60) 指定元素合并
c1.splice(++c1.begin(),c2,++c2.begin(),c2.end());
//c1(10,50,60,20,30); c2(40) 指定范围合并
25. swap()交换两个链表(两个重载)
c1.swap(c2); //c1(40,50,60);
swap(c1,c2); //c1(40,50,60)
26. unique()删除相邻重复元素(断言已经排序,因为它不会删除不相邻的相同元素)
c1.unique();
//假设c1开始(-10,10,10,20,20,-10)则之后为c1(-10,10,20,-10)
c1.unique(mypred); //自定义谓词
list 的使用
在使用list必须包括头文件#include <list>,
1)、如何定义一个list对象
#include <list>
int main (void)
{
list<char > cList; //声明了list<char>模板类 的一个实例
}
2)、使用list的成员函数push_back和push_front插入一个元素到list中
cList. push_back(‘a’); //把一个对象放到一个list的后面
cList. push_front (‘b’); //把一个对象放到一个list的前面
3)、使用list的成员函数empty()判断list是否为空
if (cList.empty())
{
printf(“this list is empty”);
}
4)、用list< char >::iterator得到指向list的指针
list< char>::iterator charIterator;
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支持随机存取。
5)、用STL的通用算法count()来统计list中的元素个数
int cNum;
char ch = ’b’;
cNum = count(cList.Begin(), cList.end(), ch); //统计list中的字符b的个数
说明:在使用count()函数之前必须加入#include <algorithm>
6)、用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()更加复杂的评估以确定一个对象是否应该被记数。
7)、使用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的指针。
8)、使用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的指针。
9)、使用list的成员函数sort()排序
cList.sort();
10)、使用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指出的位置以前。
11)、如何在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’);
C++ list类详解的更多相关文章
- java之StringBuffer类详解
StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...
- java之AbstractStringBuilder类详解
目录 AbstractStringBuilder类 字段 构造器 方法 public abstract String toString() 扩充容量 void expandCapacity(in ...
- java之StringBuilder类详解
StringBuilder 非线程安全的可变字符序列 .该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍).如果可能,建议优先采用该类,因为在 ...
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- QAction类详解:
先贴一段描述:Qt文档原文: Detailed Description The QAction class provides an abstract user interface action tha ...
- JAVAEE学习——struts2_01:简介、搭建、架构、配置、action类详解和练习:客户列表
一.struts2是什么 1.概念 2.struts2使用优势以及历史 二.搭建struts2框架 1.导包 (解压缩)struts2-blank.war就会看到 2.书写Action类 public ...
- Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解
1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...
- C# 内置 DateTime类详解
C# 内置 DateTime类详解 摘抄自微软官方文档,用来方便自己查阅:网址:https://msdn.microsoft.com/zh-cn/library/system.datetime(v=v ...
- Android游戏开发之旅 View类详解
Android游戏开发之旅 View类详解 自定义 View的常用方法: onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) ...
- Java 枚举类详解
1. 枚举类定义 在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象,这种实例有限而且固定的类,在Java里被称为枚举类. 2. 早期实现枚举的方式 public static f ...
随机推荐
- Maven核心知识
什么是Maven? Maven是基于项目对象模型(POM), 可以通过一小段描述信息来管理项目的构建和文档的软件项目管理工具 目录结构如下 src main java package test jav ...
- CodeForces 131D【图特性+BFS】
题意: 只有一个环,然后环都是0(环缩点相当于树的根),然后其余的输出到根的距离 思路: 可以从度为1的 开始搜 把那些分支全标记掉,然后再取没有标记掉的,BFS一下搞出距离. 具体这个标记: 倒着搜 ...
- 帝都Day7——解放篇
昨天晚上的problems: songfen 坠大子段和,要把[l,r]其中一个数变成P,我们要把最小的数变成p. 当L,R没有取满整个区间,P可以在[L,R]外面!!!!!!!这种情况真是令人绝望. ...
- 打开powerDesigner时,创建table对应的自动生成sql语句没有注释
在创建pdm时由于需要在name列填写的是以后要在表中创建的注释信息,comment中则写的说明信息字数比较多.默认情况下在生成建表sql时不能将name生成注释信息,进行如下设置可以讲name生成注 ...
- BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)
先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...
- poj 1236 Network of Schools (强连通分量+缩点)
题目大概: 每个学校都可以把软件复制好,交给它名单上的学校. 问题A:把软件复制成几份,然后交给不同的学校,所有学校才能够都有软件. 问题B:添加几条边,能使得这个图变成强连通图. 思路: 找出所有的 ...
- 【手撸一个ORM】第七步、SqlDataReader转实体
说明 使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不 ...
- 02-----body签中相关标签
大纲 字体标签: h1~h6.<font>.<u>.<b>.<strong><em>.<sup>.<sub> 排版标 ...
- JAVA内存模型(Java Memory Model ,JMM)
http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...
- POJ 1556 E - The Doors
题意:给定n堵墙,现在要你从(0,5)走去(10,5)的最短距离 思路:刚开始还想模拟,就是从(0,5)走,每次x向右一格,然后判断有没和线段相交就可以.但是它的们有可能是小数形式给出的,这样就GG了 ...