- They allow us to pass data type as a parameter.
- Defined as:
template<typename T>
- At compile time, template will expand.
- STL: Standard Template Library
- Set of template classes for implementing commonly used data structures and functions.
- Examples: vector, list, set, map, queue, stack, etc.
- Containers
- Iterators
- Algorithms
- They are used to hold data of the same type.
- Examples:
- Vector: Class that defines a dynamic array.
- List: Class for doubly linked list.
- Map: Class used to store unique key-value pairs.
- Set: Class used to store unique values.
- These are used to iterate/traverse the containers.
- They are pointer-like entities.
- Example:
vector<int> v = {1, 2, 3, 4, 5};
vector<int>::iterator itr;
itr.begin(); //will return 1.
- These are functions that are used to manipulate data in the containers.
- Examples: sort(), min(), max();
- It is a template class in STL for implementing a doubly linked list.
#include<list>
// list<data_type> list_name
list<int> list1;
list<int> list2{1, 2, 3, 4};
list<int> list3 = {5, 6, 7, 8};
- Implementation becomes easy.
- list.begin(): iterator for the first element
- list.end(): iterator for the position after the last element
- list.rbegin(): iterator for the first element in reverse iteration
- list.rend(): iterator for the position after the last element in reverse position
- advance(itr, n): advances the itr by n places
- list.insert(itr, value): inserts value before the position of the itr
- list.insert(itr, count, value): insert value count number of times before itr
- list.insert(itr, start_itr, end_itr): insert values from start_itr to end_itr before itr
- list.erase(itr): deletes the element pointed to by the itr
- list.erase(start_itr, end_itr): deletes elements from start_itr to end_itr (end_itr is not included)
- push_front(val): inserts val in the front of the list
- pop_front(): removes value from from front of the list
- push_back(val): inserts val in the back of the list
- pop_back(): removes val from back of the list
- Set is an STL container used to store unique values.
- It stores values in ordered state (either in increasing order or decreasing order).
- There is no indexing, elements are identified by their own values.
- Once value is inserted in a set, it cannot be modified. Value becomes constant.
- It is implemented internally using a Red Black Tree.
- When we need to store unique values
- When we need to store data in ordered manner
- Has dynamic size, so there is no overflowing errors
- Faster data structure; insertion, deletion and search are in O(log n)
- Cannot access elements using indexing
- Requires more memory than array
- Not suitable for large datasets as insertion and deletion can be costly
#include<set>
// set<data_type> set_name;
set<int> set1 = {1, 2, 3, 4};
// set<datatype, greater<datatype>> set_name; --> for decreasing order
By default, values are stored in increasing order.
- set_name.insert(value);
- Time Complexity: O(log n)
- Returns an iterator to the inserted value
- using iterator
- set_name.begin(): iterator pointing to the first element of set
- set_name.end(): iterator pointing to the position after the last element of set
- set_name.erase(value): deletes value from set
- set_name.erase(position): deletes value from set pointed to position
- set_name.erase(start_pos, end_pos): deletes elements from start_pos including it till end_pod excluding end_pos
- Time Complexity: O(log n) but for the last one, it will be O(n) as number of elements is in the range
- size(): get size of set
- max_size(): get maximum number of elements set can hold
- empty(): returns true if set is empty, else false
- clear(): removes all elements from set
- find(): returns position of element if present, else returns end iterator
- count(): returns number of occurrences of an element, returns 1 if value is present, else returns 0
- lower_bound(): returns element if present, else returns greater value
- upper_bound(): returns the next greater value
- begin(): returns iterator to the first element of the set
- end(): returns iterator pointing to the position after the last element of set
- rbegin(): returns iterator to the first element in reverse order
- rend(): returns iterator to the position after the last element in reverse order
- Values are stored in unordered fashion.
- It stores unique values which will be identified by itself.
- Values cannot be modified inside set.
- On average, time complexity for insertion, deletion and search is O(1) using Hashing.
#include<unordered_set>
// unordered_set<data_type> set_name;
unordered_set<int> set1 = {1, 2, 3, 4};
- insert(): inserts elements in a set
- s.insert(value) Time Complexity in case of single element: O(1) in average case and O(N) in worst case (when size>=capacity) Time Complexity in case of multiple elements: O(n) in average case where n = number of elements being inserted and O(n*(N+1)) in worst case where n = number of elements being inserted and N = size of unordered set
- erase(): deletes elements from a set
- s.erase(value)
- s.erase(iterator)
- s.erase(start_itr, end_itr) Time Complexity in case of single element: O(1) in average case and O(N) in worst case (when size>=capacity) Time Complexity in case of multiple elements: O(n) in average case where n = number of elements being deleted and O(n*(N+1)) in worst case where n = number of elements being deleted and N = size of unordered set
- find(): returns value of element if present, else returns end iterator
- s.find(ele) Time Complexity: O(1) in average case and O(N) in worst case
- count(): returns number of occurrences of an element, returns 1 if value is present, else returns 0
- s.count(ele) Time Complexity: O(1) in average case and O(N) in worst case
- load_factor(): returns value of (size of unordered set/bucket count)
- rehash(x): sets the number of buckets to x or more Time Complexity: O(N) in average case and O(N*N) in worst case
- Multiset can store duplicate values.
- It stores values in ordered manner (ascending/descending).
- Value will be identified by itself.
- Value can't be modified in multiset.
#include<set>
// multiset<data_type> set_name;
set<int> set1 = {1, 2, 3, 4};
// multiset<datatype, greater<datatype>> set_name; --> for decreasing order
- insert(): inserts elements in a set
- s.insert(value) Time Complexity: O(log N)
- erase(): deletes elements from a set
- s.erase(value) --> removes all duplicate values as well
- s.erase(iterator)
- s.erase(start_itr, end_itr) Time Complexity: O(log N), O(log N) and O(N)
- find(): returns lower bound of element searched if found, else returns end iterator
- s.find(ele) Time Complexity: O(log N)
- count(): returns number of occurrences of an element
- s.count(ele) Time Complexity: O(k + log N)
- lower_bound(): returns iterator pointing to first occurrence of value if present, else returns next greater value
- s.lower_bound() Time Complexity: O(log N)
- upper_bound(): returns the position of next greater value
- s.upper_bound() Time Complexity: O(log N)
- Unordered Multiset can store duplicate values.
- It stores values in an unordered manner.
- Value will be identified by itself.
- Values can't be modified in unordered multiset.
- It is implemented using Hashing.
#include<unordered_set>
// unordered_multiset<data_type> set_name;
unordered_multiset<int> set1 = {1, 2, 3, 4};
- insert(): inserts elements in a set
- s.insert(value) Time Complexity in case of single element: O(1) in average case and O(N) in worst case (when size>=capacity) Time Complexity in case of multiple elements: O(n) in average case where n = number of elements being inserted and O(n*(N+1)) in worst case where n = number of elements being inserted and N = size of unordered multiset
- erase(): deletes elements from a set
- s.erase(value) --> removes all duplicate values as well
- s.erase(iterator)
- s.erase(start_itr, end_itr) Time Complexity: O(1) in average case and O(N) in worst case (when size>=capacity)
- find(): returns lower bound of element searched if found, else returns end iterator
- s.find(ele) Time Complexity: O(1) in average case and O(N) in worst case (when size>=capacity)
- count(): returns number of occurrences of an element
- s.count(ele) Time Complexity: O(n) in average case where n = number of occurrences and O(N) in worst case where N = size of unordered multiset
- Map is an STL Container which stores key-value pairs.
- A map is used to make a solution efficient.
- The elements (i.e. key-value pairs) are stored in ascending or descending order.
- Maps can't have duplicate keys i.e. keys are unique.
- Maps in C++ are implemented through Binary Search Tree.
#include<map> //header file required
//map<datatype_of_key, datatype_of_value> map_name = {{key1, value1}, {key2, value2}};
map<string, int> phone_dir = {{"Naman", 1234}, {"Aman", 2345}};
By default, order is ascending.
For descending order-
//map<datatype_of_key, datatype_of_value, greater<datatype_of_key>> map_name;
phone_dir.insert(make_pair("ABC", 4567));
//or
phone_dir["ABC"] = 4567;
- Using for each loop
/*for(auto element:map_name){
key = element.first;
value = element.second
}*/
//Here element is a key-value pair.
- erase(): delete some elements from map
- m_name.erase(it) --> using iterator (used to traverse our STL Container)
- m.erase(key)
- m.erase(start_itr, end_itr) --> key-value pair at end_itr doesn't get deleted Time Complexity: O(log N), O(log N), O(N)
- swap(): swap two maps of same type
- m1.swap(m2)
- swap(m1, m2)
- clear(): delete all elements from map
- m.clear()
- empty(): returns 1 if empty, otherwise 0
- m.empty()
- size(): returns number of key-value pairs
- m.size()
- max_size(): Space allocated to map in memory
- m.max_size()
- find(): returns iterator to the element if present, else returns m.end() iterator
- m.find(key) Time Complexity: O(log N)
- count(): returns number of occurrences of key
- m.count(key)
- It will return 1 if key is present as keys are unique.
- upper_bound(): returns an iterator to the next greater element
- m.upper_bound()
- lower_bound(): returns iterator to the element if present, else iterator to the next greater element
- m.lower_bount()
- begin(): returns iterator to the first element
- m.begin()
- end(): returns iterator to the position after the last element
- m.end()
- rbegin(): returns iterator to the first element in reverse order
- m.rbegin()
- rend(): returns iterator to the position after the last element in reverse order
- m.rend()
Maps are dynamic containers, like: lists, vectors, etc.
- It is an STL container that stores key-value pairs.
- Elements are not ordered in an unordered map.
- Keys will be unique.
- Insertion, Deletion and Retrieval/Search are done in O(1).
- Unordered map is implemented using Hashing.
#include<unordered_map> //header file required
//unordered_map<datatype_of_key, datatype_of_value> map_name = {{key1, value1}, {key2, value2}};
- Using for each loop
/*for(auto element:map_name){
key = element.first;
value = element.second
}*/
//Here element is a key-value pair.
- erase(): delete some elements from map
- m_name.erase(it)
- m.erase(key)
- m.erase(start_itr, end_itr) Time Complexity in any case: O(1) Time Complexity in worst case: O(n)
- insert(): insert elements into the map
- m.insert(make_pair(key, value)) Time Complexity in any case: O(1) Time Complexity in worst case: O(n)
- find(): returns iterator to the element if present, else returns m.end() iterator
- m.find(key) Time Complexity in any case: O(1) Time Complexity in worst case: O(n)
- count(): returns number of occurrences of key
- m.count(key)
- It will return 1 if key is present as keys are unique.
- begin(): returns iterator to the first element
- m.begin()
- end(): returns iterator to the position after the last element
- m.end()
- It is an STL container that stores key-value pairs.
- Elements are stored in an order - ascending or descending.
- Duplicate keys are allowed.
- Multimap is implemented using Binary Search Tree.
- Insertion, Deletion and Retrieval/Search are done in O(log N).
#include<map> //header file required
//multimap<datatype_of_key, datatype_of_value> map_name = {{key1, value1}, {key2, value2}};
For descending order-
//map<datatype_of_key, datatype_of_value, greater<datatype_of_key>> map_name;
phone_dir.insert(make_pair("ABC", 4567));
- Using for each loop
/*for(auto element:map_name){
key = element.first;
value = element.second
}*/
//Here element is a key-value pair.
- erase(): delete some elements from map
- m_name.erase(it)
- m.erase(key)
- m.erase(start_itr, end_itr) Time Complexity: O(log N), O(log N), O(N)
- insert(): insert elements into the map
- m.insert(make_pair(key, value)) Time Complexity: O(log N)
- find(): returns iterator to the element if present, else returns m.end() iterator
- m.find(key) Time Complexity: O(log N)
- count(): returns number of occurrences of key
- m.count(key)
- begin(): returns iterator to the first element
- m.begin()
- end(): returns iterator to the position after the last element
- m.end()
- equal_range(): returns bounds of range of elements with keys passed
- m.equal_range()
- It is an STL container that stores key-value pairs.
- Elements are not stored in an ordered way.
- Duplicate keys are allowed.
- Multimap is implemented using Hashing.
- Insertion, Deletion and Retrieval/Search are done in O(1) in average case and O(N) in worst case.
#include<unordered_map> //header file required
//unordered_multimap<datatype_of_key, datatype_of_value> map_name = {{key1, value1}, {key2, value2}};
For descending order-
//unordered_multimap<datatype_of_key, datatype_of_value, greater<datatype_of_key>> map_name;
phone_dir.insert(make_pair("ABC", 4567));
- Using for each loop
/*for(auto element:map_name){
key = element.first;
value = element.second
}*/
//Here element is a key-value pair.
- erase(): delete some elements from map
- m_name.erase(it)
- m.erase(key)
- m.erase(start_itr, end_itr) Time Complexity: O(1), O(1), O(N)
- insert(): insert elements into the map
- m.insert(make_pair(key, value)) Time Complexity: O(1)
- find(): returns iterator to the element if present, else returns m.end() iterator
- m.find(key) Time Complexity: O(1)
- count(): returns number of occurrences of key
- m.count(key) Time Complexity: O(N) where N = Number of occurrences
- begin(): returns iterator to the first element
- m.begin()
- end(): returns iterator to the position after the last element
- m.end()
Summary: Ordered + Unique Keys: Map Not ordered + Unique Keys: Unordered Map Not ordered + Duplicate Keys: Unordered Multimap Ordered + Duplicate Keys: Multimap