C++——Explanation of list linked list of STL container

Table of contents

1. Introduction to list

2. Explanation of list class member functions

        2.2 Iterator

3. Add and delete data:

        3.1 added:

        3.2 Deletion of data

 4. Sorting and deduplication functions:

The error cases are as follows:

Methods as below:


1. Introduction to list

        A list is a sequence container that allows operations such as inserting or deleting elements at any position within the sequence. The bottom layer of the list list container is encapsulated by a linked list, and the type of the linked list is still a headed bidirectional circular linked list.

2. Explanation of list class member functions

       As for the member functions of the list container, their functions are not much different from those of the vector and String containers. They are all adding, deleting, checking and modifying, and can traverse or modify the data of an element in the container through iterators. Due to the difference between the underlying types of the former and the latter two, it is shown from the side that the use of the list container is plug-and-play and does not require expansion or contraction, which means that there will be no functions such as reserve() and shrink_to_fit().

       

        2.2 Iterator

        The iterators of the list linked list container are also different from the iterators of String and Vector. The latter two use native pointers. Due to the continuous address space, the pointer only needs to increase or decrease the bytes of the type to locate the specific pointer. Location.

        For the List container, its elements are nodes one after another, and each node is connected by a pointer, so the addresses of each node are not continuous. It will be quite complicated to use native pointers to find the element position, so the list Iterator is a new type of iterator, made with a custom type.

        Although the bottom layer of the list iterator is different from the iterators of string and vector, the usage methods are the same:

vector<T>:: iterator vt=v.begin();

String:: iterator st=s.begin();

list<T>::iterator lt=l.begin();

They are all defined by adding a class domain and a scope qualifier iterator. 

         Among iterators, they are also divided into ordinary iterators, const iterators, reverse iterators, and const reverse iterators. The functions of each member are the same as those of String and vector containers discussed before, so I won’t explain them in detail here. If you are not sure, you can read the explanation of String and vector containers that I wrote before.

 Here is the exercise code directly:

#include<iostream>
#include<list>
int main(){
    list<int> l1;
	l1.push_back(1);
	l1.push_back(2);
	l1.push_back(3);
	l1.push_back(4);
	for (auto& e:l1) {
		cout << e << " ";
	}
	cout << endl;

    list<int>::iterator lit1 = l1.begin();
	while (lit1 != l1.end()) {
		cout << ++(*lit1) << " ";
		++lit1;
	}
	cout << endl;

	cout << "--------------------------------------------" << endl;

	//反向迭代器
	list<int>::reverse_iterator lit2 = l1.rbegin();
	while (lit2 != l1.rend()) {
		cout << ++(*lit2) << " ";
		++lit2;
	}
	cout << endl;

    //const反向迭代器
    list<int>::const_reverse_iterator lit3 = l1.crbegin();
    while (lit3!= l1.crend()) {
	    cout << (*lit3) << " ";
	    //cout << ++(*lit3) << " ";			//报错
	    ++lit3;
    }
    cout << endl;

    //const正向迭代器
    list<int>::const_iterator lit4 = l1.cbegin();
    while (lit4 != l1.cend()) {
    	//cout << ++(*lit3) << " ";			//报错
    	cout << (*lit4) << " ";
	    ++lit4;
    }
    cout << endl;
    }
        return 0;
    }

operation result: 

 

 

 

3. Add and delete data:

        3.1 added:

int main(){
    list<double> l2;
	//尾插
	l2.push_back(9.25);
	l2.push_back(60.10);
	l2.push_back(32.19);
	l2.push_back(58.79);
	//头插
	l2.insert(l2.begin(), 3.14);
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//尾插
	l2.insert(l2.end(),999.99);
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//中间插
	//find是std库函数中的
	auto pos = find(l2.begin(), l2.end(), 32.19);
	l2.insert(pos, 46.99);
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//头插push_front
	l2.push_front(12.66);
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;
    return 0;
    }

 

 

        Note: For insert, its formal parameter needs to specify the pos position of the pointer type, and the pos position needs to be located in the linked list by itself. In the code above, I use the library function find to locate it, and the list container itself does not provide it. find function, because the find function formal parameters and return value in the library can help us locate it very well.

And I said before that in the vector container, the insert function will cause pointer invalidation problem, but in the list, the insert function will not cause this problem.

 

 

 

        3.2 Deletion of data

    list<char> l2;
	l2.push_back('a');
	l2.push_back('b');
	l2.push_back('c');
	l2.push_back('d');

	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//尾删
	l2.pop_back();
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//头删
	l2.pop_front();
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//中间删——erase
	l2.push_back('h');
	l2.push_back('i');
	l2.push_back('j');
	l2.push_back('k');
	
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

	//find是std库函数中的
	auto pos = find(l2.begin(), l2.end(), 'p');
		//l2.erase(pos);		//找不到的删会报异常
	for (auto& e : l2) {
	cout << e << "  ";
	}
	cout << endl;

	 pos = find(l2.begin(), l2.end(), 'h');
	l2.erase(pos);
	for (auto& e : l2) {
		cout << e << "  ";
	}
	cout << endl;

operation result: 

 

 

 4. Sorting and deduplication functions:

 

void Test6() {
	list<int> l1;
	l1.push_back(34);
	l1.push_back(100);
	l1.push_back(26);
	l1.push_back(79);
	l1.push_back(83);
	l1.push_back(0);
	l1.push_back(34);
	l1.push_back(55);
	l1.push_back(13);
	for (auto& e : l1) {
		cout << e << " ";
	}
	cout << endl;

	//排序
	l1.sort();
	for (auto& e : l1) {
		cout << e << " ";
	}
	cout << endl;

    }

 

 The sort() function can sort the elements of the list object as a whole.

        Deduplication is to traverse the linked list object, delete multiple elements with the same element value, and retain only the only value node.

 

Perform element deduplication on the above object l1:

l1.unique();
	cout << "去重后的链表:";
	for (auto& e : l1) {
		cout << e << " ";
	}
	cout << endl;

result: 

 

        Here is the actual usage of the unique function. Although the unique function can deduplicate elements in a linked list, the premise is that the linked list must be in a completely ordered state! !

        If the linked list is not ordered, deduplication will be invalid! ! !

The error cases are as follows:
    list<int> l2;
	l2.push_back(34);
	l2.push_back(100);
	l2.push_back(26);
	l2.push_back(79);
	l2.push_back(83);
	l2.push_back(0);
	l2.push_back(34);
	l2.push_back(55);
	l2.push_back(13);
	cout << "原链表:";
	for (auto& e : l2) {
		cout << e << " ";
	}
	cout << endl;
	l2.unique();
	//注:34仍是俩个,没有被去除
	cout << "去重后的链表:";
	for (auto& e : l2) {
		cout << e << " ";
	}
	cout << endl;

 

        The original linked list is unordered. After using the unique function, the linked list still has multiple duplicate elements!

        Finally, I would like to emphasize: the sort function of the list container is not easy to use, and the sorting efficiency is low. Use it as little as possible! If you want to perform efficient sorting, you can use the vector container with the sort function in the std library. 

Methods as below:
void Test_Sort(){
    list<int> lt1;
    lt1.push_back(15);
    lt1.push_back(9);
    lt1.push_back(3);
    lt1.push_back(10);
    lt1.push_back(80);    
    lt1.push_back(5);
    lt1.push_back(-3);
    lt1.push_back(0);
    lt1.push_back(42);
    //假设链表中有这么多数据

    vector<int> v;    //创建vector对象
	v.reserve(9);    //根据链表对象的数据个数开辟空间

	//通过遍历lt1链表,将链表中的数据一个一个尾插到vector对象v中,
	for (auto e : lt1)
	{
		v.push_back(e);
	}
	//使用vector方式进行std库中的sort排序
	sort(v.begin(), v.end());
	size_t i = 0;
	//最后将vector排好序的数据在传回lt1中
	for (auto& e : lt1){
		e = v[i++];
	    }
    }

        If the amount of data that needs to be sorted by the list container object is too large, using vector sort + sort is much more efficient than using list.sort() directly.

Guess you like

Origin blog.csdn.net/weixin_69283129/article/details/131963219