Article Directory
1. The use of list
First of all, before using the list, we must first understand what the list is. Looking at the documentation , we can learn that the bottom layer of the list is a leading two-way circular linked list.
In order, let's first understand the default member function of list. Here we don't pay attention to the parameters of allocator later.
1. Constructor
Let's take a look at a piece of code:
void Test_construct()
{
list<int> lt1;
list<int> lt2(5, 2);
list<int> lt3(lt2.begin(), lt2.end());
list<int> lt4(lt3);
}
2. The use of iterators and data access
We know that the emergence of the iterator design pattern is to allow all containers to have a unified access method, so the use of iterators here is no different from the string and vector mentioned before.
void Test_Iterator()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
//写
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
*it *= 10;
++it;
}
//读
it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
But for string and vector, we have three ways to access data: [] subscript access, iterator, range for. The purpose of using [] access is that the time complexity of accessing any element is O(1), but for the structure of the list: linked list, we cannot achieve O(1) access, so there is no heavy It is necessary to load [], so there are only two ways to access the list: iterator and range for .
3. Capacity related
1. size : Get the number of data in the list
Due to the structure of the list, there is no concept of capacity, because every time data is inserted or deleted, a node can be directly inserted or deleted. So here only the size interface is provided to return the number of data.
2. resize : change the number of data
Same usage as interfaces of other STL containers
3. clear : Clear all data in the container
void Test_Capacity()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
cout << "size:" << lt.size() << endl;
lt.resize(5);
cout << "size:" << lt.size() << endl;
lt.resize(10, 20);
cout << "size:" << lt.size() << endl;
auto begin = lt.begin();
while (begin != lt.end())
{
cout << *begin << " ";
++begin;
}
cout << endl;
lt.clear();
cout << "size:" << lt.size() << endl;
}
4. Data modification
Due to the particularity of the linked list structure, we can easily insert at the head, end or at any position, so there are many ways for data insertion in this library
1. Data insertion
1. push_back : tail plug
2. push_front : head plug
3.insert : Insert and delete at any position
void Test_insert()
{
vector<int> v(5, 888);
list<int> lt;
//尾插
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
auto it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
//头插
lt.push_front(10);
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
//在任意位置插入
auto it_push = ++lt.begin();//从第二个位置开始
lt.insert(it_push, 30);//插入一个值
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
++it_push;
lt.insert(it_push, 5, 50);//插入n个值
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
++it_push;
lt.insert(it_push, v.begin(), v.end());//插入一个迭代器区间
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
}
2. Data deletion
Corresponding to data insertion, data deletion also has three
1. pop_back : tail delete
2.pop_front : header deletion
3.erase : delete anywhere
void Test_erase()
{
list<int> lt;
for (int i = 0; i < 10; ++i)
{
lt.push_back(i);
}
auto it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
//头删
lt.pop_front();
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
//尾删
lt.pop_back();
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
//任意位置删除
auto pos = ++lt.begin();
pos = lt.erase(pos);//删除某一位置
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
auto start = ++pos;
auto end = ++(++start);
lt.erase(start, end);//删除一个迭代器区间
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
}
5. Other interfaces
In addition to the above-mentioned interfaces, there are some interfaces that we haven't seen in string and vector before. Let's take a look at their usage
1. remove : delete the specified value in the list
void Test_remove()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
lt.push_back(7);
lt.push_back(8);
auto it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
lt.remove(5);
lt.remove(10);
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
}
As you can see, remove does not do anything to elements that do not exist in the list
2. sort : sort list
Seeing this, some people will definitely have doubts. Hasn’t the sort algorithm library been implemented? Why do I have to re-implement it in the list again, can't I just use the ones in the algorithm library?
✅The answer is: no, let’s see the experiment==》
It can be seen that an error has been reported during the compilation process. This is because the library does not support the structure of the list iterator type. Why? Because sort used + and - operations on the elements inside the container before, but due to structural limitations, the list does not support this behavior of the iterator, so for the list, it is necessary to re-implement a sort in the library.
3. unique : delete duplicate values in the list
Note here, make sure that the list is in order before using unique, otherwise the function of deleting all duplicate values cannot be completed
void Test_Sort()
{
list<int> lt;
lt.push_back(1);
lt.push_back(10);
lt.push_back(9);
lt.push_back(3);
lt.push_back(6);
lt.push_back(3);
lt.push_back(7);
lt.push_back(6);
cout << "原list:";
auto it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
lt.unique();
cout << "尝试在乱序的情况下使用unique:";
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
lt.sort();
cout << "排序list:";
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
cout << "对有序的list使用unique:";
lt.unique();
it_out = lt.begin();
while (it_out != lt.end())
{
cout << *it_out << " ";
++it_out;
}
cout << endl;
}