[C++] The use of linked list (list) and the difference from vector

1. Introduction to list

In C++, std::listit is a container class provided by the standard library for chain storage of data. A linked list (list) is a non-continuous storage structure on a physical storage unit. The logical order of data elements is implemented through pointer links in the linked list.

  • Composition of linked list: Linked list consists of a series of nodes .
  • The composition of the node: 1. Data field to store data elements 2. Pointer field to store the address of the next node .

The linked list in STL is a bidirectional circular linked list . Since the storage method of the linked list is not a continuous memory space, the iterator in the linked list only supports forward and backward movements and is a bidirectional iterator .


2. The difference between std::list and std::vector

  1. Low-level implementation:

    • listIs implemented by a doubly linked list, each element contains pointers to the previous and next elements. This implementation makes inserting and deleting elements anywhere in the list efficient, but has poor performance for random access to elements.
    • vectorIt is implemented by a dynamic array, and the elements are stored continuously in memory. This implementation makes the performance of random access to elements very good, but inserting/removing elements in the middle or at the beginning involves moving elements, and the performance is relatively low.
  2. Dynamic resizing:

    • listThe size of can grow and shrink dynamically because it uses a linked list to store elements, and the performance of insertion and deletion operations is independent of the size of the list.
    • vectorThe size can also grow dynamically, but this may result in a large number of element copying and memory reallocation operations when memory needs to be reallocated.
  3. Access efficiency:

    • listRandom access is not supported, only sequential access via iterators. For scenarios that require frequent insertion and deletion operations, listthe performance is better.
    • vectorSupports random access, elements can be accessed directly through subscripts. For operations that require frequent random access, vectorthe performance is better.
  4. Memory usage:

    • listWhen storing elements, in addition to the value of the element itself, additional space is required to store pointers to the previous and next elements. Therefore, it usually vectoruses more memory than .
    • vectorWhen storing an element, only the value of the element itself and some additional control information need to be stored, so it usually uses listless memory than .
  5. Insertion and deletion operations:

    • listIt is efficient for inserting and deleting elements at arbitrary positions because it only requires modifying the pointers of adjacent elements and does not require moving other elements. listThere is an important property. Neither insertion nor deletion operations will cause the original list iterator to become invalid. This vectoris not true in .
    • vectorIt is efficient for inserting and deleting elements at the end because it only needs to operate at the end of the array and does not require moving other elements. But when inserting/removing elements in the middle or beginning, other elements need to be moved.

To sum up, choosing to use listor vectordepends on the specific application scenarios and needs. You can choose this if frequent insertion and deletion operations are required and frequent random access to elements is not required list. If you need frequent random access to elements and fewer insertion and deletion operations, you can choose it vector. In addition, if you need to perform insertion and deletion operations in the middle of the container, and the access efficiency is not high, you can consider using it list.


3. List constructor

Constructor prototype explain
1 list<T> lt Default constructor, implemented using template classes
2 list(lt.begin(), lt.end()) Copy the elements in the lt[begin, end) interval to itself
3 list(n, Element) The constructor copies n Elements to itself
4 list(const list &lt) copy constructor

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
    
    
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}
void printVec(list<double> &v)
{
    
    
	for (list<double>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
    
    
	list<int> v1;
	v1.push_back(10);  //添加元素
	v1.push_back(20);
	printVec(v1);

	list<int> v2(v1.begin(), v1.end());
	printVec(v2);

	list<double> v3(5, 6.32);
	printVec(v3);

	list<double> v4(v3);
	printVec(v4);
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
10 20
10 20
6.32 6.32 6.32 6.32 6.32
6.32 6.32 6.32 6.32 6.32

Notice:

When list is used as a parameter or return value of a function, the "&" cannot be missing.


4. List assignment

Function prototype: =, assign explain
1 list& operator=(const list &lt) Overloaded = operator
2 assign(begin, end) Copy and assign the data in the [begin, end) interval to itself
3 assign(n, Element) Assign n Element copies to itself

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
    
    
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
    
    
	list<int> v1;
	v1.push_back(10);  //添加元素
	v1.push_back(20);
	printVec(v1);

	list<int> v2 = v1;
	printVec(v2);

	list<int> v3;
	v3.assign(v1.begin(), v1.end());
	printVec(v3);

	list<int> v4;
	v4.assign(6, 1);
	printVec(v4);
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
10 20
10 20
10 20
1 1 1 1 1 1

5. List length operation

Function prototype: empty, size, resize explain
1 empty() Determine whether the container is empty
2 size() Returns the number of elements in the container
3 resize(int num) Respecify the length of the container to num. If the container becomes longer, the new position is filled with the default value; if the container becomes shorter, the elements at the end that exceed the length of the container are deleted.
4 resize(int num, Element) Respecify the length of the container to num. If the container becomes longer, the new position is filled with the Element value; if the container becomes shorter, the elements at the end that exceed the length of the container are deleted.

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
    
    
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
    
    
	list<int> v1;
	if (v1.empty())     //判断是否为空
	{
    
    
		cout << "当前v1为空!" << endl;
	}

	v1.push_back(10);  //添加元素
	v1.push_back(20);
	v1.push_back(30);

	if (!v1.empty())
	{
    
    
		cout << "v1中元素个数:" << v1.size() << endl;
		printVec(v1);
	}

	v1.resize(5);
	printVec(v1);

	v1.resize(10, 1);
	printVec(v1);
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
当前v1为空!
v1中元素个数:3
10 20 30
10 20 30 0 0
10 20 30 0 0 1 1 1 1 1

6. List insertion and deletion

Function prototype: push_back, pop_back, insert, erase, clear explain
1 push_back(Element) Insert element at the end
2 pop_back() Remove last element
3 push_front(Element) Insert an element at the beginning of the container
4 pop_front() Remove the first element from the beginning of the container
5 insert(iterator p, Element) The iterator points to position p to insert the element Element
6 insert(iterator p, int n, Element) The iterator points to position p and inserts n elements Element
7 insert(p,iterator start, iterator end) Insert data in the interval [start, end) at position p, no return value
8 erase(iterator p) Delete the element pointed to by the iterator
9 erase(iterator start, iterator end) Delete the elements from start to end of the iterator
10 remove(elem) Delete all elements in the container that match the elem value
11 clear() Delete all elements in the container

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
    
    
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
    
    
	list<int> v1;
	v1.push_back(1);  //尾部添加元素
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(3);
	cout << "尾部添加元素: " << endl;
	printVec(v1);

	v1.pop_back();    //尾部删除元素
	cout << "尾部删除元素: " << endl;
	printVec(v1);

	v1.push_front(100);  //头部添加元素
	v1.push_front(200);
	v1.push_front(300);
	cout << "头部添加元素: " << endl;
	printVec(v1);

	v1.pop_front();   //头部删除元素
	v1.pop_front();
	cout << "头部删除元素: " << endl;
	printVec(v1);

	v1.insert(v1.begin(), 100);      //插入元素100
	cout << "插入元素100: " << endl;
	printVec(v1);

	v1.insert(v1.begin(), 5, 100);   //插入5个元素100
	cout << "插入5个元素100: " << endl;
	printVec(v1);

	v1.erase(v1.begin());    //删除元素
	cout << "删除元素v1.begin(): " << endl;
	printVec(v1);

	v1.remove(100);
	cout << "删除所有100元素: " << endl;
	printVec(v1);

	v1.clear();				 //清空容器
	printVec(v1);
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
尾部添加元素:
1 2 3 3
尾部删除元素:
1 2 3
头部添加元素:
300 200 100 1 2 3
头部删除元素:
100 1 2 3
插入元素100:
100 100 1 2 3
插入5个元素100:
100 100 100 100 100 100 100 1 2 3
删除元素v1.begin():
100 100 100 100 100 100 1 2 3
删除所有100元素:
1 2 3

7. List data acquisition

Function prototype: front(), back explain
1 front() Returns the first data element in the container
2 back() Returns the last data element in the container

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void test01()
{
    
    
	list<int> v1 = {
    
     1, 2, 3, 4, 5, 6 };
	cout << "v1.front() = " << v1.front() << endl;
	cout << "v1.back() = " << v1.back() << endl;
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
v1.front() = 1
v1.back() = 6

8. List exchange, reversal, sorting

Function prototype: swap, reverse, sort explain
1 swap(list lt) Swap the elements in lt with its own elements
2 reverse() Reverse linked list
3 sort() Linked list sorting

Example:

#include <iostream>
#include <list>     //必须包含该头文件
using namespace std;

void printVec(list<int> &v)
{
    
    
	for (list<int>::iterator At = v.begin(); At != v.end(); At++)
	{
    
    
		cout << *At << " ";
	}
	cout << endl;
}

void test01()
{
    
    
	list<int> v1 = {
    
     9, 5, 7, 8, 6 };
	list<int> v2 = {
    
     5, 4, 3, 2, 1 };

	v1.swap(v2);   //互换v1与v2中的元素
	cout << "list v1 : " ;
	printVec(v1);
	cout << "list v2 : " ;
	printVec(v2);

	v2.sort();  //链表排序
	cout << "v2链表排序 : ";
	printVec(v2);

	v2.reverse();  //反转链表v2
	cout << "v2反转链表 : ";
	printVec(v2);
}

int main()
{
    
    
	test01();
	system("pause");
	return 0;
}
//result
list v1 : 5 4 3 2 1
list v2 : 9 5 7 8 6
v2链表排序 : 5 6 7 8 9
v2反转链表 : 9 8 7 6 5

If this article is helpful to you, I would like to receive a like from you!

Insert image description here

Guess you like

Origin blog.csdn.net/AAADiao/article/details/131214952
Recommended