STL的list类¶
C++中有已经做好的标准模版库STL,STL中的list类是双向链表,功能强并且健壮。
链表可以保存数据,链表里面有一个指针指向下一个数据元素
双向链表有两个指针,一个指向下一个节点,一个指向前一个节点。
链表就是很多个节点,一个节点一个节点通过指针连成一条链。
链表比数组好的优点¶
链表比较方便,可以在任何地方插入数据(开头,结尾,中间),都是非常快的。插入所需要的时间是固定的,不会随数据增多而增加。数组只在末尾插数据比较快。
- 实例化std::list对象
- 在list中间插入元素
- 删除list中的元素
- 对list中的元素进行反转和排序
如何使用STL list双向链表¶
#include <list>//C++ STL中的链表 导入头文件
using namespace std;//list也是用的std命名空间
void test()
{
list<int> a;//a就是双向链表
a.push_front(10);
a.push_front(2001);
a.push_front(-1);
a.push_front(9999);//每次都是从头插入,新插入的都在最前面
}
链表迭代器¶
C++的链表做的还有一个迭代器,通过迭代器可以把链表中的数据一个一个的进行处理。
所以自己设计的链表也应该有迭代器功能。增加一个迭代器。
做一些复杂的数据结构的时候,需要自己写。
#include <list>//C++ STL中的链表
//标准C++ STL中的链表和迭代器
//可以往链表的前面增加数据,也可以往链表的后面增加数据
list<int> listIntegers;
listIntegers.push_front(5);//在链表前面插入数据
listIntegers.push_front(15);
listIntegers.push_front(25);
listIntegers.push_front(35);
//想要看链表中的数据 使用迭代器
list<int>::iterator i = listIntegers.begin();//迭代器 返回第一个数据
//迭代器是一个指针
cout << *i << "->";
while (i != listIntegers.end()) {
cout << *i << "->";
++i;//下一个元素
}
cout << endl;
操作类私有的数据成员。需要做成友元类。
插入数据¶
1、从list开头插入¶
a.push_front(9999);//每次都是从头插入,新插入的都在最前面
2、从list末尾插入¶
a.push_back(8989);//往链表后端插入
3、在list中间插入¶
有三种方法
第一种方法:
//中间插入数据
//用迭代器指定位置
a.insert(a.begin(), 10);//在begin头插
insert方法 第一个参数是一个迭代器 指定插入的位置,a.begin()
就是头部插入。第二个参数是插入的数据。
第二种情况:
a.insert(a.end(), 4, 20);//在末端插入4个20
第三种情况:
通过迭代器指定位置,可以在任意位置插入数据
void test()
{
list<int> a;//a就是双向链表
//显示链表中的数据不能使用下标,因为不是数组,数组才可以用下标
//链表只能使用迭代器
std::list<int>::iterator iter;//迭代器类型
a.push_front(4);
a.push_front(3);
a.push_front(2);
a.push_front(1);//每次都是从头插入,新插入的都在最前面
a.push_back(5);//往链表后端插入
iter = a.begin();//迭代器指向位置
++iter;//变成第二个位置
a.insert(iter, 10);//在第二个位置插入10
++iter; //改变位置
a.insert(iter, 4, 20);//插入4个20
//中间插入数据
//用迭代器指定位置
a.insert(a.begin(), 10);//在begin头插
a.insert(a.end(), 4, 20);//在后端插入4个20
//通过a.begin()得到迭代器
for (iter = a.begin(); iter != a.end(); ++iter) {
cout << *iter << endl;//迭代器是指针
}
}
改变迭代器的位置。
通过控制迭代器,利用insert
在链表的中间插入数据。
迭代器指定插入的位置。
取元素,查看元素,链表不能使用下标,没有下标。只能使用迭代器。
//显示链表中的数据不能使用下标,因为不是数组,数组才可以用下标
//链表只能使用迭代器
std::list<int>::iterator iter;//迭代器类型 创建一个迭代器
//通过a.begin()得到迭代器
for (iter = a.begin(); iter != a.end(); ++iter) {
cout << *iter << endl;//迭代器是指针
}
打印list中的数据:¶
void PrintListContents(const list<int>& listInput)
{
std::list<int>::const_iterator iter;//常迭代器
//通过a.begin()得到迭代器
for (iter = listInput.begin(); iter != listInput.end(); ++iter) {
cout << *iter << endl;//迭代器是指针
}
}
把一个list中的数据插入到另一个list中:¶
两个list。
把b插入到a里面:
b插入到a的前面:
a.insert(a.begin(), b.begin(), b.end());
b插入到a的后面:
a.insert(a.end(), b.begin(), b.end());
也可以插入到中间
iter = a.begin();
++iter;//变成第二个位置
a.insert(iter, b.begin(), b.end());
也可以这样:
a.insert(iter, ++b.begin(), --b.end());
b.begin()是一个迭代器,b.end()也是一个迭代器。
指的是位置。第一个位置,最后一个位置。
++b.begin()从b的第二个开始
--b.end(),b的倒数第二个 结束。b最后一个不插入。
insert第一个参数是迭代器 从哪儿插入
第二个 第三个参数也是迭代器,是一个区间。插入的数据。
上面三个insert函数是函数重载,完成不一样的功能。
删除list中的元素¶
往list中insert的时候,就会返回一个迭代器
并且这个迭代器就指向insert的这个数据的位置。
std::list<int> a;
a.push_front(4);
a.push_front(3);
list<int>::iterator iElementValueTwo;
iElementValueTwo = a.insert(a.begin(), 2);//insert返回一个迭代器 迭代器指向这个数据
iElementValueTwo迭代器就指向2。
通过迭代器删除:
a.erase(iElementValueTwo);
这样就把迭代器指向的2给删了。
删除的时候也可以给两个迭代器,从第一个迭代器到第二个迭代器区间的所有数据都删除。
a.erase(a.begin(), iElementValueTwo);
左闭右开,包括a.begin()这个 但是不包括iElementValueTwo迭代器指向的2。
两次删除:
a.erase(a.begin(), iElementValueTwo);
a.erase(iElementValueTwo, a.end());
从开始到2,从2到最后,a.end()指向的是最后一个的后一个,这样就删完了。
可以通过迭代器删除迭代器指向的数据。
反转数据¶
a.reverse();
排序数据¶
a.sort();
list标准模版库,里面有各种方法,还有迭代器。
可以直接使用,不需要再重新写了。非常方便。