Container in c++
Classification
- Sequence container
- Associative container
Associative container have a key-value pair. It do not have back and front so they never have push_back, pop_back.
Vector
This is similar with grow array. Vector use sequential space.
insert(position, n, x)
When the number of element from position to end is bigger than the number of new element, move directly may cause overlap.
vector<bool>
vector<bool> is not array of boolean type data. It actually convert to bit array. Each bit will represent a bool value.
List
Actually, list is a circular double linked list.
Here is proof that list have a circular:
|
|
List have an empty node which end() point to. The next of this empty node is begin and the previous of begin is the empty node.
transfer()
transfer() can move some element in specific range*( [first, last) )* to a specific location.
It is a basic function to move element in list and foundation of other complicated function like sort(), reverse(), splice().
|
|
sort()
list have it own sort algorithm. List cannot use std::sort() because this function need RandomAccessIterator instead of BidirectionalIterator.
This algorithm is O(nlogn). It roughly a merge sort. This website has a sample show the algorithm step by step.
But STL sort algorithm is better.
Deque
Deque is a continuous linear space. Deque can insert and remove element at begin and end. Technically, vector has same function but is inefficient.
Deque do not have capacity, therefore push and pop on back and front in constant time.
Deque provide Random Access Iterator but it iterator is not same with vector and very complicated. If want sort deque, copy to vector, sort and copy back.
When deque space has been filled, it will connect a continuous space. Therefore, deque use separate continuous linear space.
Deque structure:
If 20 integer in a deque, the iterator is:
Stack
Stack is deque which close one end. STL design stack base on deque, therefore stack is not classified as container but classified as adopter.
FILO
NO iterator
Can be implemented by list.
Queue
Similar thing with stack. FIFO.
NO iterator
Can be implemented by list.
Heap
Heap is not a container in STL but it is the basement of priority_queue.
Heap is a complete binary tree and array can store all elements in heap. However, we want to change the capacity of array. We can use a vector and some algorithm to make up a heap.
No iterator
push_heap
Add one element in heap
pop_heap
Pop one element
push and pop is not swap element. It actually manipulate the location.
Because pop the an element and put it at the end of array, you can adjust the rest of elements by make_heap.
|
|
sort_heap
After pop a element, will stay at the end of array. After pop all element, heap must empty and array is sorted.
make_heap
Make a range of elements into heap.
usage
|
|
Priority_queue
priority_queue is adopter with heap algorithm.
No iterator
Vector + make_heap
Forward_list
Forward_list is a single linked list.
Forward iterator
insert_after() & erase_after()
In c++, insert() and erase() will add or remove element before the position your given. But it is more cost that insert or erase in a single linked list. Therefore, forward_list only provide insert_after() and erase_after() which you can add or remove element after the position your provided.
push_front() & pop_front()
Unlike queue and priority_queue only provide push and pop at end, forward_list just allow you push and pop at beginning because it is a single linked list.
No size()
Forward_list not provide size().
RB tree
See another post: RB Tree
Set
Set only have key.(Or key and value is same.)
Set not allow duplication.
Set are base on RB tree.
The iterator of set is const_iterator. You cannot modify any element through iterator.
STL::find() is work. But better using set::find().
Map
Map have key-value pair.
Map not allow duplication on key.
Map are base on RB tree.
You can modify the value by iterator bu not the key. Therefore, it neither a const_iterator nor mutable_iterator.
STL::find() is work. But better using map::find().
Map could use operator[] to access by providing a key. But the problem is that if the key your provided not exist in map, that will insert this key. Therefore, if you want to modify value but not add new key-value pair, you can use map.at(). If you just want to know this exist or not, you can use map.count() which will return 1 or 0.
|
|
multimap & multiset
Could have several key.
HashTable
Linear probing
Quadratic probing
After find a collision, Change the hash function.
Multiplication is not good, especially i power 2.
Hi = H0 + i2(mod M)
Hi+1 = H0 + (i+1)2(mod M)
But we can do:
Hi+1 - Hi = (i+1)2(mod M) - i2(mod M)
Hi+1 - Hi = (i+1)2 - i2(mod M)
Hi+1 - Hi = 2i + 1 (mod M)
Hi+1 = Hi + 2i + 1 (mod M)
We can use left shift to multiple 2 which is a acceptable method.
Separate chaining
C++ use separate chaining to achieve hash table.
In STL, hash table use a vector and linked-list (not list in STL).