简介:链表是一个双向的结构,与string与vector不同的是他不支持[]访问,因为链表是由一个节点一个节点连接而成的,并不连续。我们可以在常数量级内对于链表进行插入与删除数据
1.构造函数
我们在cplusplus.com中可以查到链表总共有四种构造的方式:1.无参构造(默认构造);2.使用n个val构造;3.迭代器区间构造; 4.拷贝构造
接下来让我们简单创建一个链表并对其进行遍历
cpp
//n个val构造
list<int> lt(5, 1);
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
2.迭代器的简要了解
2.1按照功能分类
iterator:迭代器
reverse_iterator:反向迭代器
const iterator:只读迭代器
const reverse_iterator:只读反向迭代器
2.2按照性质分类
单向迭代器:forward_list/unordered_map/unorder_set......只支持 ++ 操作
双向迭代器:list/map/set........支持 ++ 、-- 操作
随机迭代器:string/vector/deque.........支持 ++ 、-- 、+ 、- 操作
还有两种迭代器可以作为了解,他们就是只读与只写迭代器,根据箭头各种迭代器之间可以近似理解为包含关系,即若一个函数参数要求单项迭代器,那么双向迭代器的参数同样可以,但是反之则不可以
比如如果我们使用不匹配的迭代器就有可能出错,例如库函数中的sort要求随机迭代器,因为其底层函数需要进行 - 的操作,如果是双向迭代器就无法进行该操作,就会报错
cpp
list<int> lt(5, 1);
sort(lt.begin(), lt.end());//错误,库函数中的sort要求使用随机迭代器类型
3.常用接口以及注意事项
3.1push_back
尾插函数,注意push_back只能插入单个数据,无法直接插入(1,1)这样类型的函数
cpp
//n个val构造
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.2emplace_back
尾插函数,与push_back不同的是,emplace_back可以直接插入(2,2)这样的数据
cpp
struct A
{
public:
A(int a1 = 1,int a2 = 1)
:_a1(a1)
,_a2(a2)
{}
int _a1;
int _a2;
};
list<A> lt;
A aa1(1, 1);
lt.push_back(aa1);
lt.push_back(A(2, 2));//匿名对象
//lt.push_back(2, 2);//报错
lt.emplace_back(aa1);
lt.emplace_back(A(2, 2));
lt.emplace_back(2, 2);//可以直接尾插
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.3insert
在指定位置之前插入数据,可以使用循环实现在任意位置插入数据
cpp
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.insert(lt.begin(), 10);//在首位前插入数据
//在第k个位置之前插入数据
auto it = lt.begin();
int k = 3;
while (k--)
{
it++;
}
lt.insert(it, 30);
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.4erase
删除指定位置数据
cpp
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
int x = 0;
cin >> x;
auto it = find(lt.begin(), lt.end(), x);
//如果find没有找到就会返回第二个参数也就是lt.end()
while (it != lt.end())
{
lt.erase(it);
}
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.5reverse
逆置链表
cpp
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.reverse();
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.6sort
库函数中的sort函数不支持链表,所以链表自实现了一个sort函数来进行排序,默认是升序,可以使用仿函数来进行降序的调整即lt.sort(greater<int>())与lt.sort(less<int>())
cpp
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.sort();
//迭代器遍历
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.7merge
将两个有序链表进行合并,如果将second链表合并到first链表,则second链表就会置空,其合并的原理就是取小尾插到被合并链表
cpp
list<int> first;
first.push_back(1);
first.push_back(2);
first.push_back(3);
first.push_back(4);
list<int> second;
second.push_back(10);
second.push_back(20);
second.push_back(30);
second.push_back(40);
first.merge(second);
//范围for遍历
for (auto e : first)
{
cout << e << " ";
}
cout << endl;
//范围for遍历
for (auto e : second)
{
cout << e << " ";
}
cout << endl;
3.8unique
去重,注意只能对有序数据去重
cpp
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.unique();
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
3.9splice
剪切另一链表的指定数据到被粘贴链表,被剪切链表中被剪切的数据会直接删除,也可以对自身进行操作,即变化自身链表数据的顺序
cpp
list<int> first;
first.push_back(1);
first.push_back(2);
first.push_back(3);
first.push_back(4);
list<int> second;
second.push_back(10);
second.push_back(20);
second.push_back(30);
second.push_back(40);
auto it = first.begin();
it++;
first.splice(it, second);//在First链表的第一个位置之后粘贴剪切后的数据
//范围for遍历
for (auto e : first)
{
cout << e << " ";
}
cout << endl;
//范围for遍历
for (auto e : second)
{
cout << e << " ";
}
cout << endl;
list<int> lt(5, 1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
int k = 0;
cin >> k;
auto it = find(lt.begin(), lt.end(), k);
if(it != lt.end())
{
lt.splice(lt.begin(), lt, it);
}
cout << endl;
//范围for遍历
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;