[C++] use of list

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.

image-20230421153930048

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

image-20230421154853012

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);
}

image-20230421155815223

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.

image-20230422133446094

2. resize : change the number of data

image-20230422235713605

Same usage as interfaces of other STL containers

3. clear : Clear all data in the container

image-20230422235840390

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;
}

image-20230423000207920

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

image-20230422134237008

2. push_front : head plug

image-20230422134217660

3.insert : Insert and delete at any position

image-20230422134302155

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;
}

image-20230422135621556

2. Data deletion

Corresponding to data insertion, data deletion also has three

1. pop_back : tail delete

image-20230422135837432

2.pop_front : header deletion

image-20230422135820204

3.erase : delete anywhere

image-20230422135902241

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;
}

image-20230422141427934

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

image-20230423000514372

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;
}

image-20230423001231333

As you can see, remove does not do anything to elements that do not exist in the list

2. sort : sort list

image-20230423001550739

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==》

image-20230423002516367

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

image-20230423003100595

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;
}

image-20230423004016031

Guess you like

Origin blog.csdn.net/weixin_63249832/article/details/130313118