STL 中 list 的使用
list 容器实现了双向链表的数据结构,数据元素是通过链表指针串连成逻辑意义上的线性表,这样,对链表的任一位置的元素进行插入、删除和查找都是极快速的。由于list对象的节点并不要求在一段连续的内存中,所以对于迭代器,只能通过++
或--
的操作将迭代器移动到后继/前驱节点元素处。而不能对迭代器进行+n
或-n
的操作,这点是与vector等不同的地方。
特点:
- 线性容器
- 常数时间增删改
- 常数时间查(已知迭代器条件下)
- 支持双向操作
缺点:
- 只能对迭代器进行 '++'、 ' -- '操作 不能进行 '+ n '、'- n' 操作 (因为不是连续存储)
头文件
#include <list>
using namespace std;
声明与定义
1、声明:
list<T> lst; // T 为节点类型
2、构造函数
list([结点个数]) // 构造具有 [结点个数] 个的列表 // 需要结点类型提供构造函数
list([结点个数], [结点对象]) // 构建的列表中包含 [结点个数] 个 [结点对象]
list([列表的起始位置], [列表的结束位置]) // 选取其他列表的一部分建立新的列表,[起始位置,结束位置)
例子
list<T> lst1(9);// 包含 9 个结点,每个结点按照 T 给的构造函数构建
list<T> lst2(5,T(1));// 建一个含5个元素的链表,每个节点都是一个 T(1) 构造的对象 //直接传入对象的话 list会自行拷贝多份
list<T> lst3(lst1.begin(),--lst1.end()); // 从别的列表中提取一部分作为当前列表,此例子中包含 8 个结点
3、初始化
可以使用 assign 方法对列表进行初始化。使用方法与构造函数基本相同,不赘述。
clear 方法清空列表。
lst.clear();
属性读取
size() // 获取列表的元素个数
empty() // 判断列表是否为空
int n = lst.size();
bool isEmpty = lst.empty();
栈操作
push_front([结点对象]); // 在列表头入栈
front();//获取列表头元素
pop_front();//列表头出栈
push_back([结点对象]);// 在列表尾入栈
back();
pop_back();
lst.push_front(t);
T t = lst.front();
lst.pop_front();
lst.push_back(t);
T t = lst.back();
lst.pop_back();
添加元素
insert 方法与构造函数相比多了一个插入位置而已。
insert ([插入位置], [结点对象]); // 就在插入位置这个相对位置插入元素,插入位置与之前元素的对应关系不会变,具体可以见下面的例子
insert ([插入位置], [结点个数], [结点对象]);
insert ([插入位置], [列表的起始位置], [列表的结束位置]);
//假设 lst2: 1 1 1 1 1 。此时迭代器 i 指向 第二个 1。t1 对应值为 3
j = lst2.insert(i, t1); // lst2: 1 3 1 1 1 1 // 在 i 位置的前面插入对象 t1,
// 此时迭代器 i 指向 第二个 1 ,迭代器 j 指向 第一个 3
j = lst2.insert(i, 3, t1);
j =lst2.insert(i, lst.begin(), lst.end());
查找元素
list 自身没有提供查找用的函数。需要使用STL的通用函数 find。
[迭代器] find([起始位置], [结束位置], [查找对象]); //
i = find(lst.begin(), lst.end(), t); // 注意:对于自己定义的类型,需要重载 '==' 运算符
删除元素
remove([迭代器指向的对象]);
erase([删除位置]); // 删除该位置的结点,返回该结点之后的迭代器
erase([起始位置], [结束位置]);// 删除 [起始位置,结束位置) 内的元素 ,返回结束位置的迭代器
lst.remove(*i);
i = lst.erase(i);
i = lst.erase(lst2.begin(), lst2.end());
比较
没有现成的比较函数。想要比较的话直接取出 结点对象 进行比较。
排序
sort() // 升序排列
sort([比较函数]) // a,b两个元素比较,如果 [比较函数] 返回真,则a 排在前面
lst.sort(); // 升序排列 // 需要自定义类型重载 '<' 运算符
lst.sort(cmp); // 此处为降序
unique操作
unique 操作可以把列表中的相同元素剔除掉,至于怎么样算是相同元素可以自行定义。
使用前必须先确保列表处于有序状态。因为 unique 操作元素的比较仅限于相邻元素。
unique();
unique([判别相等的函数]);
lst.unique();
lst.unique(equal);// equal 是个函数,能返回比较结果 // 在Xcode 6 上实测,仅支持基本类型或者STL类型的对象
lst.unique(Equal());// Equal 是个类,重载 '()' 操作符
merge 操作
两个列表在合并前应当处于有序状态,并且前后使用相同的比较逻辑,这样合并后的列表也是有序的,否则合并后的列表是无序列表。
merge([列表对象])
merge([列表对象], [比较函数])
lst.merge(lst2);
lst.merge(lst2,cmp);
遍历
由于列表是一个双向链表,不能通过迭代器间的大小比较判断链表是否到达末尾,需要使用 '!=' 。
for (list<T>::iterator i = lst.begin(); i != lst.end(); ++i){
cout << (*i).a;
}
示例代码
#include<list>
#include<iostream>
using namespace std;
#define Out(T) cout << T << endl;
struct T{
int a;
T(int a){
this->a = a;
}
T(){
a = 0;
}
// find 操作时用
friend bool operator ==(const T &a,const T &b){ // friend 不能缺
return a.a == b.a;
}
friend bool operator < (const T &a,const T &b){ // friend 不能缺
return a.a < b.a;
}
// unique 操作时用
bool operator() (const T &a, const T &b)
{
// return (a.a - b.a) < 5;
return a.a == b.a;
}
};
// sort 用
bool cmp(const T &a, const T &b){
return a.a > b.a;
}
// unique 用
bool equal(const T &a, const T &b){
return a.a == b.a;
}
bool myequal(const double a, const double b){
return a == b;
}
int main(){
////////////////////////////////////////////////
// 声明与定义
list<T> lst;
list<T> lst1(9);// 包含 9 个结点,每个结点按照 T 给的构造函数构建
list<T> lst2(5,T(1));// 建一个含5个元素的链表,每个节点都是一个 T(1) 构造的对象
list<T> lst3(lst1.begin(),--lst1.end()); // 从别的列表中提取一部分作为当前列表,此例子中包含 8 个结点
////////////////////////////////////////////////
// 属性读取
Out(lst1.empty()); // 输出 0
Out(lst3.size()); // 输出 8
////////////////////////////////////////////////
// 栈操作
T t(2);
lst.push_front(t); // lst: 2
T t1(3);
lst.push_front(t1); // lst: 3 2
lst.push_back(t1); // lst: 3 2 3
Out(lst.front().a); // 输出 3
if(!lst.empty()) lst.pop_back(); // lst: 3 2
if(!lst.empty()) lst.pop_front(); // lst: 2
////////////////////////////////////////////////
// 添加元素 (入栈与出栈)
T t2(4);
list<T>::iterator i = lst2.begin(); // 迭代器指向 第一个 1
lst2.insert(++i, t1); // lst2: 1 3 1 1 1 1 // 迭代器指向第二个 1 并在它的前面插入 t1
i = lst2.insert(++i, 3, t2); // lst2: 1 3 1 4 4 4 1 1 1 // 迭代器指向第三个 1 // 返回指向第一个 4 的迭代器
++i; // 迭代器指向第二个 4
lst2.insert(i,lst.begin(), lst.end()); // lst2: 1 3 1 4 2 4 4 1 1 1
// 查找元素
i = find(lst.begin(), lst.end(), T(1)); // 注意:对于自己定义的类型,需要重载 '==' 运算符
////////////////////////////////////////////////
// 删除元素
if (i != lst.end()) {
lst.remove(*i);
// i = lst.erase(i);
// i = lst.erase(lst2.begin(), lst2.end());
}
////////////////////////////////////////////////
// 排序
lst2.sort(); // 升序排列 // 需要自定义类型重载 '<' 运算符
lst2.sort(cmp); // 此处为降序
////////////////////////////////////////////////
// unique 操作
lst.unique();
// lst.unique(equal);// equal 是个函数,能返回比较结果 // 不支持自定义类型
lst2.unique(T());// Equal 是个类,重载 '()' 操作符
list<double> a(5,4);
a.unique(myequal); // 支持基本类型
// merge
lst3.assign(3, T(3));
lst2.sort();
lst3.sort();
lst2.merge(lst3);
lst2.merge(lst3,cmp);
////////////////////////////////////////////////
// 遍历元素
for (list<T>::iterator i = lst2.begin(); i != lst2.end(); ++i){
cout << (*i).a << ' ';
}
Out("");
}
STL 中 list 的使用的更多相关文章
- STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- STL中的next_permutation
给定一个数组a[N],求下一个数组. 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 ..... 在STL中就有这个函数: 1.参数是(数组的第一个元素,数组的末尾),注意这是前闭后开 ...
- 3.2 STL中的函数对象类模板
*: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...
- C++的模板特化 和 STL中iterator_traits模板的偏特化
C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...
- C++的STL中vector内存分配方法的简单探索
STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux CentOS 5.2 1.代码 #include <vector> #include <stdio ...
- C++ STL中vector(向量容器)使用简单介绍
原文:http://www.seacha.com/article.php/knowledge/cbase/2013/0903/2205.html C++ vector(向量容器)是一个线性顺序结构.相 ...
- 深入了解STL中set与hash_set,hash表基础
一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...
- 【转】 STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- C++ STL中Map的按Key排序和按Value排序
map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区 分),我们用map来进 ...
- (转)STL中set的用法
转载自here 1.关于set map容器是键-值对的集合,好比以人名为键的地址和电话号码.相反地,set容器只是单纯的键的集合.例如,某公司可能定义了一个名为bad_checks的set容器,用于记 ...
随机推荐
- IT兄弟连 HTML5教程 和页面布局有关的CSS属性
使用DIV+CSS对网页进行标准化布局前,除了要掌握盒子模型,还要掌握定位和浮动两个比较重要的概念,它们可以控制在页面上排列和显示元素的方式.一个盒子是装内容的区块,如果多个盒子组合在一起使用,再通过 ...
- 文件系统之parted 分区
parted分区命令 1.分区表区别 我们 Linux 系统中有两种常见的分区表 MBR 分区表(主引导记录分区表)和 GPT 分区表(GUID 分 区表) MBR 分区表:支持的最大分区是 2TB( ...
- JQuery之Ajax基础
众所周知JQuery中的Ajax主要用于数据传输,其数据传输格式为JSON格式数据,比XML格式数据传输更快. ajax 是 Asynchronous JavaScript and XML的简写,aj ...
- 1.1 菜单管理 ——MyRapid WinForm快速开发框架-功能介绍
菜单表数据库设计 可以根据数据表取得树状目录,其中 版本和作者 可以分别对版本和修改人进行追溯 有兴趣的朋友可以尝试再添加一个收藏夹 也是比较常用的功能 这里我没有做这个功能 然后看下菜单编辑 ...
- jquery仿淘宝购物车页面商品结算(附源码)
1.效果图如下: 2.源码如下: html部分: <!doctype html> <html lang="en"> <head> <met ...
- linux_ext4恢复超级块.txt
恢复ext4文件系统superblock 2014-04-01 17:00:17 分类: Linux 恢复ext4文件系统superblock1. Create ext4 文件系统.[root@loc ...
- celery执行异步任务和定时任务
一.什么是Clelery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统 专注于实时处理的异步任务队列 同时也支持任务调度 Celery架构 Celery的架构由三部分组成,消息中间件 ...
- Python语法速查: 13. 操作系统服务
返回目录 本篇索引 (1)sys模块 (2)os模块 (3)与Windows相关模块 (4)subprocess模块 (5)signal模块 (1)sys模块 sys模块用于Python解释器及其环境 ...
- NFS挂载遇到的问题
问题描述:生产环境中需要经常运用NFS挂载,就在测试环境中测试一下,将服务器中192.168.1.4 /u01/app/oracle/product/11.2.0/dbhome_1/dbs 挂载到1 ...
- JavaScript-----7.循环
1.循环 在JS中主要有以下三种类型的循环 for循环 while循环 do...while循环 2. for循环 2.1 语法结构如下: for (初始化变量: 条件表达式: 操作表达式) { // ...