目录
🤔list模板介绍:
🤔特点:
🤔list内存结构图解:
🤔 list的成员函数:
😊list构造函数:
🔍代码示例:
🔍运行结果:
😊list赋值函数:
🔍代码实例:
🔍运行结果:
😊list判断函数:
🔍代码实例:
运行结果:
😊 list的删除和插入
🔍代码实例:
运行结果:
😊list存取函数
🔍代码实例:
🔍运行结果:
😊 list反转和排序函数:
🔍代码实例:
🔍运行结果:
😊 list实用特殊函数:
🔍2.merge:
🔍3.cbegin,crbegin,cend,crend
结束!
🤔list模板介绍:
📖C++中的list是一个双向链表模板类,提供了一系列方便的链表操作方法,比如在列表前后插入/删除元素、访问节点和迭代器等。它的底层实现是双向链表、由节点构成的结构,节点包含指向前一个节点和后一个节点的指针,使得链表的查找、插入和删除操作都比较高效。与vector相比,list不支持随机访问,但提供了更快的在任意位置进行插入和删除操作能力,list一般用于动态添加或删除元素比较多的情况,例如LRU缓存中存储最近使用过的数据。
🤔特点:
📖1. 双向链表结构:list以双向链表的形式存储元素,每个节点包含一个元素值和指向前一个和后一个节点的指针。因此,在list中插入、删除元素可以较为高效地实现。
📖2. 不支持随机访问:list不支持随机访问,并不能像vector和array一样通过下标来访问节点,而需要通过迭代器或指针来操作。
📖3. 动态添加和删除元素:由于其底层为链表结构,list可以在任意位置高效地进行元素插入、删除操作,而不需要移动其他元素,通过这一点,list可以用于需要频繁添加和删除元素的场景。
4. 迭代器支持:list提供了迭代器的支持,可以通过迭代器遍历整个链表,或者实现反向遍历。
📖5. 内存空间管理:list为每个元素分配堆空间,因此不同于vector,list对元素的添加或删除操作能够避免因为内存重分配带来的性能损失。
📖6. 没有实现数据的置换:list中不包含像set和map这些关联式容器实现的数据置换机制。如果需要实现数据的置换,可以使用其他关联式容器,例如红黑树,AVL树等。
📖7. list迭代器不支持加减操作:由于链表的结构和迭代器的本质,list迭代器不支持加减操作,例如it = it + 1,但支持递增和递减,例如++it和--it。
总的来说,list能够高效实现插入或删除元素,并可以通过迭代器遍历整个链表。由于需要为每个元素分配堆空间,因此list也会占用比vector更多的内存空间。
🤔list内存结构图解:
🤔 list的成员函数:
😊list构造函数:
📖1.默认构造函数:list <T> lst;
list<int>b;
📖2..将[beg,end)区间的元素拷贝给自身 : list(beg,end);
list<int>c(b.begin(),b.end());
📖3.将n个elem拷贝给本身: list(n,elem);
list<int>d(8,10);
📖4.拷贝构造函数 list (const list &list);
list<int>d(8,10);
🔍代码示例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
//区间构造为:
list<int>c(b.begin(),b.end());
cout << "区间构造结果为:";
printa(c);
//n个elem构造:
list<int>d(8,10);
cout << "n个elem构造结果为:";
printa(d);
//拷贝构造:
list<int>e(d);
cout << "赋值构造结果为:";
printa(e);
}
int main()
{
test01();
}
🔍运行结果:
😊list赋值函数:
📖1.将[beg,end)区间中的数据拷贝赋值给本身: assign(beg,end);
b1.assign(b.begin(), b.end());
📖2.将n个elem赋值给本身: assign(n,elem) ;
b2.assign(10, 8);
📖3.重载等号运算符: list & opertor =(const list &list );
list<int>b3;
b3 = b2;
📖4.将list与本身元素互换: swap();
list<int>b4;b4.swap(b3);
🔍代码实例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
list<int>b1;
b1.assign(b.begin(), b.end());
cout << "区间拷贝结果为:";
printa(b1);
list<int>b2;
b2.assign(10, 8);
cout << "区间拷贝结果为:";
printa(b1);
list<int>b3;
b3 = b2;
cout << "重载等号结果为:";
printa(b3);
list<int>b4;
b4.swap(b3);
cout << "交换后结果为:";
printa(b4);
}
int main()
{
test01();
}
🔍运行结果:
😊list判断函数:
📖1返回容器中的元素个数: size()
📖2.返回容器是否为空: empty()
📖3.重新指定容器的长度为num。若容器变长,就以默认值填充新位置,若容器变短,则超出的被删除: resize(num);
📖4.重新指定容器的长度为num。若容器变长,就以ele值填充新位置,若容器变短,则超出的被删除: resize(num,elem);
🔍代码实例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
cout << "b容器是否为空(1为空,0不为空)" << b.empty()<<endl;
cout << "b容器的大小为:" << b.size()<<endl;
b.resize(11);
cout << "无ele的resize结果为:";
printa(b);
cout << endl;
b.resize(12,9);
cout << "有ele的resize结果为:";
printa(b);
}
int main()
{
test01();
}
运行结果:
😊 list的删除和插入
📖1.在容器尾部加入一个容器 push_back(elem);
📖2.删除容器中最后一个元素 pop_back();
📖3.在容器开头插入元素 push_front(ele);
📖4.删除第一个元素 pop_front();
📖5.在pos位置插入 eleminsert(pos, elem);
📖6.在pos位置插入n个eleminsert (pos,n, elem);
📖7.在pos位置插入区间beg,end的所有元素 insert(pos,beg,end);
📖8.移除容器中的所有元素 clear();
📖9.删除beg到end的所有元素 earse(beg, end);
📖10.删除pos位置的数据 earse(pos);
📖11.删除容器中所有与ele匹配的值 remove(ele);
🔍代码实例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
b.push_back(1);
cout << "在尾部插入数字后:";
printa(b);
b.pop_back();
cout << "在尾部删除数字后:";
printa(b);
b.push_front(1);
cout << "在头部插入数字后:";
printa(b);
b.pop_front();
cout << "在头部删除数字后:";
printa(b);
b.insert(b.begin(), 98);
cout << "在头部插入数字98后:";
printa(b);
b.insert(b.begin(), 3,98);
cout << "在头部插入3个数字98后:";
printa(b);
b.clear();
cout << "在使用clear函数后:";
printa(b);
//重新赋值:
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
b.remove(8);
cout << "在使用参数为8的remove函数后";
printa(b);
b.erase(b.begin());
cout << "使用erase函数对begin位置删除后";
printa(b);
b.erase(b.begin(),b.end());
cout << "使用erase函数对begin到end区间删除后";
printa(b);
}
int main()
{
test01();
}
运行结果:
😊list存取函数
📖1.返回第一个元素:front()
📖2.返回最后一个元素:back()
🔍代码实例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
cout << "打印front函数的返回值:";
cout << b.front();
cout << endl;
cout << "打印back函数的返回值:";
cout << b.back();
}
int main()
{
test01();
}
🔍运行结果:
😊 list反转和排序函数:
📖1.反转链表 reverse();
📖2.排序 sort();
🔍代码实例:
#include<iostream>
using namespace std;
#include<list>
void printa(const list<int>& d)
{
for (list<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//默认构造为:
list<int>b;
for (int i = 0; i < 10; i++)
{
b.push_back(i);
}
cout << "默认构造结果为:";
printa(b);
cout << "调用reverse函数之后";
b.reverse();
printa(b);
cout << endl;
cout << "调用sort函数之后:";
b.sort();
printa(b);
}
int main()
{
test01();
}
🔍运行结果:
😊 list实用特殊函数:
🔍1.unique:
📖在C++ STL的list容器中,unique是一个函数,它用于去除list容器中邻近并且相等的元素,时间复杂度为O(N),其中N为list容器大小。
template<class T> void list<T>::unique();
📖该函数检查容器中相邻的元素,并删除重复的元素。
📖举个例子,如果list容器中包含如下元素:{1, 2, 2, 3, 3, 3}
,那么如果你调用unique函数,它将会把容器变为:{1, 2, 3}
,即将每个相邻并且相等的元素删除并仅保留一个。
📖需要注意的是,在使用unique函数之前必须将list容器进行排序,因为该函数仅能识别相邻、相等的元素,如果元素未排序,它将无法正确地识别相邻的元素是否相等。
📖如果需要自定义去重的判定条件,可以将自定义的判断函数作为参数传递给unique函数,这样它可以根据自定义规则去重。例如:
bool compare(int a, int b) {
return abs(a) < abs(b);
}
int main() {
std::list<int> mylist { 1, 2, -2, 3, -3, -3 };
mylist.sort();
mylist.unique(compare);
for (auto it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
📖该代码使用自定义比较函数compare()
,它将每个元素的绝对值作为比较条件,去除相邻的绝对值相等的元素,输出结果为1 2 3
。
🔍2.merge:
📖在C++ STL的list容器中,merge()函数用于将两个已排序的list容器合并为单个list,并保持其排序顺序。该函数的用法如下:
template<class T> void list<T>::merge(list<T>& x);
📖该函数将x的元素合并到当前容器中,并确保保持排序顺序。
📖举个例子,如果有两个list容器,分别为:
std::list<int> list1 { 1, 3, 5 };
std::list<int> list2 { 0, 2, 4 };
📖如果你对它们进行merge()操作,那么list2中的元素将被移动到list1容器中,并保持排序顺序,最终list1容器变为:{0, 1, 2, 3, 4, 5}。
📖需要注意的是,在使用merge()函数之前必须将list容器进行排序,否则结果将是未定义的。
🔍3.cbegin,crbegin,cend,crend
📖cbegin()
和 cend()
返回指向容器中第一个元素和最后一个元素的常量迭代器。其中,最后一个元素指的是那个值与 list::end() 的返回值相等的元素的下一个位置。这些函数的返回类型是 const_iterator
,这意味着它们返回的迭代器是指向常量值的。
📖而 crbegin()
和 crend()
则返回指向容器中最后一个元素和第一个元素的常量反向迭代器。这些函数的返回类型是 const_reverse_iterator
。