#include< array >//Static array
#include< vector >//It can be expanded and contracted, and the size of the array can be dynamically applied according to the amount of data
#include< list >//Circular double-linked list
#include< forward_list >//Single-linked list
#include< deque >//Double-ended queue
#incldue< stack >//Stack
#incldue< queue >//Queue
Introduction of list
It can be iterated forward and backward for
each node to open up through malloc and new.
Under frequent insertion and deletion, it is better to use list, which is much faster than vector.
Under frequent query, it is better to use vector. Each node of list is not continuous
data. When the amount is huge, vector is much easier to find than list. When the amount of
data is huge, the basic reason for choosing vector is:
vector array: 1.** array elements are next to each other, no space wasted, and list linked list has next, prev , And header information, etc., the storage density is small 2. From the operating system , each node applies from the heap area, randomly, the heap area space is 4k as a page, and the page of the vector is continuous between pages , But in the case of a linked list, this node is stored in this page, but its next may be in other pages, and other nodes may also be applied for in other pages. When querying, the system has a page missing problem, resulting in Page out of memory. Page fault interrupted. When the vector finds the next page, page faults may be interrupted. For the linked list, searching for data, that is, in the process of next searching for the next location and searching for a page, the page fault is interrupted.
The storage density, if they are all integers, the storage density is one-third (4+4+4), which is
actually much smaller than one-third. In fact, there is a 4-byte upper out-of-bounds mark. A byte of lower out-of-bounds mark, the top 28 bytes of header information (recording the 12 bytes applied to the user, as well as other status information) and the manager of the heap area, but also a certain amount of consumption I
feel that I have applied for 12 bytes, which actually wastes a lot of space.
_M_Size: Record the number of nodes in the doubly linked list.
begin(): refers to the first node, end() refers to the last The successor of a node, the head node
member
prints list
Iterator
template<class _Ty>
class List
{
struct _Node;
typedef struct _Node* _Nodeptr;//结点的指针
struct _Node
{
_Nodeptr _Prev,_Next;
_Ty _Value;
};
private:
_Nodeptr _M_head;
_Nodeptr _M_size;
class iterator
{
public:
iterator(_Nodeptr_P=nullptr):_Ptr(_P){
}
value_type& operator*(){
return _Ptr->Value;}
value_type* operator->(){
return &_Ptr->Value;}
protected:
_Nodeptr _Ptr;
};
};
Use
iterators Print
int main()
{
list<int>ar;
list<int>br={
12,23,34,45,67,78};
//以下是用迭代器打印
list<int>::iterator it=br.begin();
for(;it!=br.end();++it)
{
cout<<*it<<endl;
}
return 0;
}
Note: list does not have overload []
but vector can use []
Usage 2:
int main()
{
list<int>ar;
list<int>br={
12,23,34,45,67,78};
for(auto x:br)//br是容器,auto x提取容器里的元素类型
{
cout<<x<<endl;
}
return 0;
}
What is the difference between these two methods.
For the built-in types, there is no difference.
For the types set by yourself, the
linked list can be inserted
from the beginning or the tail. For vectors, only from the tail, the problem of data movement is
first to call the constructor to generate an Int object, and then Pass this object to the push_back method of this linked list, construct a node, and then initialize this node with this object, calling the move construction, because Int(i) is a dead value and is unnamed.
Call the copy constructor to construct, because here a is not a dead value, it has a name
printed
The point is here.
For the libraries in the list, all have iterators.
A: Extract data from the container, and
copy the structure to x auto x one by one , which is the least efficient
B:
There will be no copy structure here
& x is an alias,
but the alias of the ar container value, ++x, is to modify the value of the container.
C:
Can only be read, not modified, and the copy structure is not mobilized.
D:
There is actually no The move structure is mobilized , and the value in ar is directly given to x. The same as the previous case, it is still an alias and can be modified. It is only an rvalue reference, and there is no move structure.
Because for ar, the data in the container is unnamed but occupied Space, not a real right value
Move construction, the parameter is an rvalue to be mobilized, instead of itself being an rvalue, you need to mobilize the
normal structure of the a object, a object has a name, call the copy constructor to construct the b object
temporary object, unnamed, call the move structure
c has a name, It is not an rvalue, and the rvalue cannot take the address . It was found that the movement structure was not mobilized during the
d
adjustment. The reason is that the compiler is optimized, and the unnamed object constructed is c itself. If the movement structure is not mobilized, the system will not mobilize the movement. Construction, the compiler is optimized, the object of return is c itself. This situation produces a temporary object a as a transition, and the system performs a move construction
The first element constructs one to x (copy construction) is
actually the first element of the container. The ++
reference in the system is equivalent
to the object pointed to by the pointer x has been released.
Now x is invalid, which is equivalent to a dangling pointer
. Return by reference, but don't use it easily when receiving!
If you receive by value, you call the constructor and build x, which has nothing to do with the objects in the container
const still cannot constrain the action of pop_front
Once deleted, this iterator becomes an invalid iterator and can no longer be used
. Inserting an Int(30) before the iterator will not cause invalidation, and the iterator point has not changed.
Will this place fail?
In the container,
for this situation, the iterator is most likely to fail. The
iterator is equivalent to the object-oriented version of the pointer
. It will fail if the possibility is relatively high. Try not to use the
vector to continuously open up space,
insert 40, but no position, expand ( Open up a new space, copy the objects one by one), delete the original space. If there is no data at the location pointed to by the iterator,
use vector to insert. Deleting elements may invalidate the iterator. Once the capacity is expanded, the memory will be opened elsewhere and
use list Insertion has no effect, because it is a node, and has nothing to do with the previous node, but the deletion is invalid
Use exchange.
This iterator is logically invalid and points to the begin() of br. It is not just exchange data when exchange.
If it is deleted, the iterator pointing will cause uncertainty, which may be the sort() of the list moved forward or empty space
;
This sorting is divided into two ways: when the amount of data is small, use quick sort, if the amount of data is large, use heap sort (the data of the ar linked list is put into the vector heap sort and then imported into the linked list).
For list, Small data, fast sorting, doubly linked lists use fast sorting
Because of the problem of the recursion depth of fast sorting, the amount of data is large, use heap sorting
The vector has no sorting function, it depends on the external, that is, the algorithm provided by the system,
but the object and the object cannot be compared. It
can be overloaded
deque
Two iterators
4 members of iterators 4 members of
queue
Data insertion: At the beginning, there is no space to
open up nodes, continuous space, pointers are placed, M_Node secondary pointer points to it, which is
equivalent to the head and tail
push_back of the queue. A new buffer configuration will occur. When it is full, a new buffer will be given. Area, no data,
but push_front is full and will not open an empty new buffer
The
biggest difference in memory configuration There is
no room, what should I do?
A new map is created, which is larger
and does not move the data.
Only the pointer is moved. The
iterator looks for
space in the left block. The difference between the original iterator
and the vector is here.
Invalid The
iterator points to begin(), and after inserting, it directly causes the iterator to fail