list的本质就是一个双向链表,操作都是依据与数据结构
forward list :向前链表,他的操作都是在链表头里
-
添加节点时,forword list 相较于list的效率高一点点,因为list有一个size的++的操作
-
list和vector的区别
-
vector随机访问很快,尾添加很快,不支持快速插入删除
-
list随机访问慢,也支持下标支持快速插入和删除
list构造函数初始化
定义一个int类型色list对象,需要添加头文件:#include <list>
- 无参构造
list<int> ls;
- 有参构造
list没有赋值的对象默认初始值为0, int类型会初始为数字类型的0,char类型会初始为char类型的0。
定义一个结构体类型的历史的对象。
Note是一个结构体类型,里面有一个int a,和char b
list<node> ls(5);
void fun(Node& d)
{
cout << d.a << " " << d.c << "\n";
}
开头和结尾都是
for_each(ls.begin(), ls.end(), fun);
- 另一个对象给一个对象初始化
list<node> ls2(ls1) ;
- 迭代器定义
list<node> ls1;
list<node>::iterator ite = ls1.begin();
迭代器可以进行++操作,但是不能+2,因为迭代器是一个非连续的空间
迭代器ite
ite++ ; //可以
ite+2 ; // 不行
属性
list没有容量,但是有大小
返回大小:size
node no = {12,'a'};
list<node> ls(6,no) ;
cout << ls.size() << endl ; //返回大小 6
- resize:重新设置元素个数,容量不变,如果重新设置了一个小的,那么会截断原来的数据
list<Node> ls(6, no);
cout << ls.size() << endl;
ls.resize(0);
判断list对象是否为空,为空的话是1,不为空的话为0
node no = {12,'a'};
list<Node> ls(6, no);
cout << ls.empty() << endl; // 不为空返回0
增删改查
添加
头添加:push_front
,尾添加:push_back
,中间添加:insert
中间添加,多个的话就是就是三个参数
struct Node
{
int a;
char c; // 0
Node(int d, char e)
{
a = d;
c = e;
}
};
头添加和尾添加
list<Node> ls;
ls.push_front(Node(12, 'a')); // 头添加
ls.push_front(Node(13, 'b')); // 头添加 , 这个是最终的头
ls.push_back(Node(14, 'c')); // 尾添加
中间添加(添加一个元素)
list<Node>::iterator ite = ls.begin();
ite++;
ls.insert(ite, Node(15, 'd')); // 中间添加,前面的++操作,会使这个添加加到第二个位置
ls.insert(ite, 3, Node(16, 'e'));
中间添加(添加多个元素)
ls.insert(ite,3,Node(13,'r')) ; // 添加三个13,r
删除、修改
删除
简答的用法:
list<Node>::iterator ite = ls.begin();
ite++;
用begin
ls.erase(ite); // 会删除ls的第二个
用end
ls.erase(--ls.end()); // 会删除最后一个
删除中间几个
两个参数 删除包含第一个参数,不包含第二个参数
list<Node>::iterator ite = ls.begin();
ite++;
用begin
ls.erase(ite,--ls.end()); // 会删除ls的第二个带最后一个前一个,删除一个参数和最后一个参数中间的
- 全部删除clear
list<Node> ls;
ls.push_front(Node(12, 'a'));
ls.push_front(Node(13, 'b'));
ls.push_front(Node(14, 'c'));
ls.push_front(Node(15, 'd'));
ls.push_front(Node(15, 'd'));
ls.push_front(Node(16, 'e'));
ls.clear();
参数相同的删除掉remove
remove需要先判断你输入的数据与所要对比中的数据是否相等。当判断两个结构体或者两个类是否相等的时候,不能直接判断需要。要在结构体或类中重新定义一个==的重载运算符。
struct Node
{
int a;
char c; // 0
Node(int d, char e)
{
a = d;
c = e;
}
重新定义一个==的重载运算符
bool operator== (const Node& f) // 参数要是const类型
{
if (f.a == this->a && f.c == this->c)
{
return true;
}
return false;
}
};
然后再
list<Node> ls;
ls.push_front(Node(12, 'a'));
ls.push_front(Node(13, 'b'));
ls.push_front(Node(14, 'c'));
ls.remove(Node(18, 'c'));
删除list中重复的元素 :unique()
修改
两个参数
用多个相同的值给list对象赋值,原来的数据都被覆盖掉
ls.assign(3, Node(2, 'c'));
swap两个list对象交换
将list1和list的内容交换
ls1.swap(ls);
reverse倒转list对象
ls.reverse();
sort()
默认从小到大排序
如果容器本身自带排序,那么使用的时候就可以不用选择排序算法
排序先要进行比较,但是某些结构体或者类的比较需要重载运算符。
struct Node
{
int a;
char c; // 0
Node(int d, char e)
{
a = d;
c = e;
}
重载一下小于号运算符
bool operator< (const Node& f)
{
if (f.a < this->a)
{
return true;
}
return false;
}
};
然后在调用排序
list<Node> ls;
ls.push_back(Node(16, 'e'));
ls.push_back(Node(15, 'd'));
ls.push_back(Node(15, 'd'));
ls.sort(); // 会按照node中第一个数据排序
从大到小的排序可以改变一下从在运算符的符号小于号改为大于号,也可以排序后在反转一下,建议改符号
ls.sort();
ls.reverse();
合并两个list对象
void merge( list &lst );
自动排序
重载小于号
两个链表必须有序
如果链表元素是升序的,就要用<号,return true
如果链表元素是降序的,就要用>号,return true
ls.merge(ls1);
拼接函数
拼接
void splice( iterator pos, list &lst );
void splice( iterator pos, list &lst, iterator del );
void splice( iterator pos, list &lst, iterator start, iterator end );