C++Standard Library Function Tutorial
In this tutorial, we will learn about Standard Library Function Tutorial in C++ with the help of examples.
Standard Library Function Tutorial
Standard Template Library (STL) is a collection of standard C++ template classes
to provide common programming data structures and functions such as lists, stacks, arrays, etc. It is a library of container classes, algorithms, and iterators. It is a generalized library and so, its components are parameterized.
Standard Template Library is basically a generic library
i.e. a single method/class can operate on different data types. So, as understood, we won’t have to declare and define the same methods/classes for different data types.
Advantages of C++ Standard library functions
- Faster Performance : Library Functions are optimised for better performance.
- Easy Syntax : syntax of library functions are very easy to learn and use.
- Optimization : Library functions are highly tested in different conditions which make them reliable to use.
- Readibility : Library functions make the code shorter ,more readable and save time of programmers.
- Portable : Library functions are available in all C++ compilers with the same meaning and serves the same purpose regardless of the operating systems we are working on.
Components of Standard Template Library
The following are the basic components provided by the C++ Standard Template Library:
1 ) Containers.
2 ) Algorithms.
3 ) Iterator.
1. Containers in Standard Template Library
Containers or container classes store objects and data. There are in total seven standard “first-class” container classes and three container adaptor classes and only seven header files that provide access to these containers or container adaptors.
Following are the different types of Containers in STL:
1. Sequence Containers
2. Associative Containers
3. Container Adapters
4. Unordered Associative Containers
Sequence Containers in Standard Template Library
Sequential Containers basically inculcate and implement the classes/functions containing the data structures wherein the elements can be accessed in a sequential manner
.
The Sequential Containers consists of the following commonly used data structures:
1. Array
2. Vector
3. List
4. deque, etc
Let’s dive into the working of some of the data structures offered by Sequential Containers.
Array
The Array class
of Sequential Containers is much more efficient than the default array structure. Moreover, elements in an array are accessible in a sequential manner.
The Sequential Containers consists of the following commonly used data structures:
Syntax:
array<data_type, size> = {value1, value2, ...., valueN};
The Array class includes a huge count of functions to manipulate the data.
Some of the most commonly used functions of the generic Array class is as follows:
array.front()
: It is used to access and print the first element of the array.array.back()
: It is used to access and print the last element of the array.array.empty()
: Checks whether the array is empty or not.array.at()
: Access and print the elements of the array.array.swap()
: Function to swap two input arrays.array.fill()
: It fills the array with a specific/particular input element.
Example
Let’s go through an example to understand the working of some basic yet common functionalities served by the Array class of Sequential Containers.
#include <iostream>
#include <array>
#include <tuple>
using namespace std;
int main() {
array <array, 4> arr = {40, 100, 0, -10};
cout << "Displaying the array elements using at(): \n";
for (int i = 0; i < 4; i++)
cout << arr.at(i) <<"" << endl;
cout << "Displaying the array elements using get(): \n";
cout << arr.get <0> (arr) <<"\n";
cout << arr.get <2> (arr) <<"\n" << endl;
cout << "First element of the array: \n";
cout << arr.front () << endl;
cout << "Last element of the array: \n";
cout << arr.back () << endl;
return 0;
}
Output
Displaying the array elements using at(): 40 100 0 -10 Displaying the array elements using get(): 40 0 First element of the array: 40 Last element of the array: -10
In the above example, #include<array>
is used to access the at()
function of Array class. The at() function is used to access the elements of the input array by traversing through a for loop.
Further, we can even use the get()
method of class tuple to access the elements by overloading the function.
The statement get<0>(arr)
enables to access and print the element at position 0 (zero) of the array.
List
The List class of the Sequential Containers provides storage to elements with non-contagious memory locations
.
Syntax:
list <data_type> list_name
Some of the most commonly used functions provided by the List class are:
list.begin()
: It returns an iterator element that points to the first element of the list.list.end()
: It returns an iterator element that points to the last element of the list.list.reverse()
: It reverses the input list.list.sort()
: This function is used to sort the input list.list.push_front(element)
: It inserts an element to the beginning of the list.list.push_back(element)
: It inserts an element to the end of the list.list.front()
: It returns the first element of the listlist.back()
: It returns the last element of the list.list.pop_front()
: This function deletes the first element of the list and decreases the size of the list by 1.list.pop_back()
: This function deletes the last element of the list and decreases the size of the list by 1.
Example
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
void display(list <int>, l){
list <int> :: iterator i;
for (i = l.begin(); i != l.end(); ++i)
cout << " \t" << *i;
cout << " \n";
}
int main() {
list <int> lst1, lst2;
for (int i = 0; i < 5; ++i){
lst1.push_front(i);
}
cout << "\nList 1: \n";
display(lst1);
cout << "Using list.front() function: \n" << lst1.front();
cout << "Using list.back() function: \n" << lst1.back();
cout << "Using list.pop_back() function: \n" << lst1.pop_back();
display(lst1);
cout << "Using list.pop_front() function: \n" << lst1.pop_front();
display(lst1);
cout << "Using list.reverse() function: \n" << lst1.reverse();
display(lst1);
cout << "Using list.sort() function: \n" << lst1.sort();
display(lst1);
return 0;
}
Output
List 1: 4 3 2 1 0 Using list.front() function: 4 Using list.back() function: 0 Using list.pop_back() function: 4 3 2 1 Using list.pop_front() function: 3 2 1 The list.reverse() function: 1 2 3 The list.sort() function: 1 2 3
In the above snippet of code, we have used an Iterator to traverse the list efficiently.
Vector
Vectors in C++ function the same way as Arrays in a dynamic manner i.e. vectors can resize
itself automatically whenever an item is added/deleted from it.
The data elements in Vectors are placed in contagious memory locations
and Iterator can be easily used to access those elements. Moreover, insertion of items in takes place at the end of Vector.
Syntax:
vector vector_name;
Most commonly used functions of Vector:
vector.begin()
: It returns an iterator element which points to the first element of the vector.vector.end()
: It returns an iterator element which points to the last element of the vector.vector.push_back()
: It inserts the element into the vector from the end.vector.pop_back()
: It deletes the element from the end of the vector.vector.size()
: This function gives the size i.e. the number of elements in the vector.vector.empty()
: Checks whether the vector is empty or not.vector.front()
: It returns the first element of the vector.vector.back()
: It returns the last element of the vector.vector.insert()
: This function adds the element before the element at the given location/position.vector.swap()
: Swaps the two input vectors.
Example
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector <int> V1;
for (int i = 0; i <= 4; i++){
V1.push_back(i);
}
cout << "Displaying elements of vector using begin() and end(): \n";
for (auto i = V1.begin(); i != V1.end(); ++i){
cout << *i <<" ";
}
cout << "\nvector.front() function: \n" << V1.front();
cout << "\nvector.back() function: \n" << V1.back();
V1.insert(V1.begin(), 8);
cout << "\nVector elements after the insertion of element using vector.insert() function: \n";
for (auto x = V1.begin(); x != V1.end(); ++x){
cout << *x <<" ";
}
return 0;
}
Output
Displaying elements of vector using begin() and end(): 1 2 3 4 Size of the input Vector: 4 Vector isn't empty vector.front() function: 1 vector.back() function: 4 Vector elements after the insertion of element using vector.insert() function: 8 1 2 3 4
In the above snippet of code, the statement V1.insert(V1.begin(), 8)
inserts the element (8) at the beginning i.e. before the first element of the vector.
Associative Containers in Standard Template Library
Associated Containers implement and inculcate generic classes and functions with sorted data structures
which in turns leads to reduced time complexity.
The following are the data structures offered by the Associative Containers:
1. Set
2. Map
3. multiset
4. multimap
Set
Sets in Associative Containers stores unique elements
i.e. redundant elements are not allowed. Moreover, once the element is inserted into the set, it cannot be altered or modified.
Syntax:
set <data_type> set_name;
Some of the commonly used functions offered by set:
set.insert(value)
: This function inserts the element to the existing set.set.begin()
: It returns an iterator element that points to the first element of the set.set.end()
: It returns an iterator element that points to the last element of the set.set.erase(position)
: It removes the element from the position or element entered.set.size()
: It returns the number of elements contained in a particular set.
Example
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
int main() {
set <int> S;
int i = 1;
while (i < 5){
S.insert(i*10);
i++;
}
set int :: iterator it;
cout << "\nInput set: \n";
for (it = S.begin(); it != S.end(); ++it){
cout <<"\t " << *it;
}
cout << endl;
int num;
num = S.erase (10);
cout << "Set after removal of element using erase() function: \n" << V1.back();
for (it = S.begin(); it != S.end(); ++it){
cout <<"\t " << *it;
}
cout << endl;
return 0;
}
Output
Input set: 10 20 30 40 Set after removal of element using erase() function: 20 30 40
Multiset
Multisets serve the same functionality as that of Sets. The only difference is that Multisets can have duplicate elements
in it i.e. it allows redundancy.
Syntax:
multiset<data_type> multiset_name;
Example
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
int main() {
multiset <int> S;
int i = 1;
while (i < 5){
S.insert(i*10);
i++;
}
S.insert(70);
S.insert(70);
multiset int :: iterator it;
cout << "\nElements of the set: \n";
for (it = S.begin(); it != S.end(); ++it){
cout <<"\t " << *it;
}
cout << endl;
int x;
x = S.erase (10);
cout << "Set after using erase() function to delete an element: \n" << V1.back();
for (it = S.begin(); it != S.end(); ++it){
cout <<"\t " << *it;
}
cout << endl;
return 0;
}
Output
Elements of the set: 10 20 30 40 70 70 Set after using erase() function to delete an element: 20 30 40 70 70
Map
Maps store elements in a key-value pair
. Each value is mapped with a key unique element.
Syntax:
map<data_type of key, data_type of element> map_name;
Some of the commonly used functions offered by Maps:
map.insert()
: This function inserts the element with a particular/specific key to the existing map.map.begin()
: It returns an iterator element that points to the first element of the map.map.end()
: It returns an iterator element that points to the last element of the map.map.size()
: It returns the number of key-value pairs in the map.map.empty()
: It checks whether the map is empty or not.
Example
#include <iostream>
#include <iterator>
#include <map>
using namespace std;
int main() {
map <int, int> M;
M.insert(pair <int, int> (1, 100));
M.insert(pair <int, int> (2, 70));
M.insert(pair <int, int> (3, 90));
M.insert(pair <int, int> (4, 20));
map <int, int> :: iterator itr;
cout << "\nInput Map: \n";
cout << "Key:value \n";
for (itr = M.begin(); itr != M.end(); ++itr){
cout << itr->first << ':' << itr->second << "\n ";
}
cout << endl;
cout << "\nMap after removal of elements: \n";
cout << "Key:value \n";
M.erase(M.begin(); itr != M.end(); +itr){
cout << itr->first << ':' << itr->second << "\n ";
}
return 0;
}
Output
Input Map: key:value 1:100 2:70 3:90 4:20 Map after removal of elements: key:value 3:90 4:20
Multimap
Multimaps function the same way as Maps, but the only difference is that in Multimaps, redundant key values
are allowed i.e. the elements can have the same key values.
Syntax:
multimap<data_type of key, data_type of element> multimap_name;
Some of the commonly used functions offered by Maps:
map.insert()
: This function inserts the element with a particular/specific key to the existing map.map.begin()
: It returns an iterator element that points to the first element of the map.map.end()
: It returns an iterator element that points to the last element of the map.map.size()
: It returns the number of key-value pairs in the map.map.empty()
: It checks whether the map is empty or not.
Example
#include <iostream>
#include <iterator>
#include <map>
using namespace std;
int main() {
multimap <int, int> M;
M.insert(pair <int, int> (1, 100));
M.insert(pair <int, int> (1, 70));
M.insert(pair <int, int> (3, 90));
M.insert(pair <int, int> (4, 20));
multimap <int, int> :: iterator itr;
cout << "\nInput Map: \n";
cout << "Key:value \n";
for (itr = M.begin(); itr != M.end(); ++itr){
cout << itr->first << ':' << itr->second << "\n ";
}
cout << endl;
cout << "\nMap after removal of elements: \n";
cout << "Key:value \n";
M.erase(M.begin(); itr != M.find(3));
for (itr = M.begin(); itr != M.end(); ++itr){
cout << itr->first << ':' << itr->second << "\n ";
}
return 0;
}
Output
Input Map: key:value 1:100 1:70 3:90 4:20 Map after removal of elements: key:value 3:90 4:20
As you can see in the above example, the first two key:value pairs have the same key. If we try the same in with “map” instead of “multimap”, only the first element with the unique key will be used while the other is dropped.
Container Adapters
Container Adapters provide a different interface to the Sequential Adapters.
Some of the commonly used data structures provided by Container Adapters are:
1. queue
2. priority queue
3. stack
Queue
Queues work in First-In-First-Out(FIFO) fashion. The items are inserted from the rear
i.e from the end and are deleted from the front
.
Syntax:
queue <data_type> queue_name;
Some of the commonly used functions offered by generic Queue:
queue.empty()
: Checks whether the queue is empty or not.queue.push(element)
: This functions adds an element to the end of the queue.queue.pop()
: It deletes the first element of the queue.queue.front()
: It returns an iterator element which points to the first element of the queue.queue.back()
: It returns an iterator element which points to the last element of the queue.
Example
#include <iostream>
#include <queue>
using namespace std;
void display(queue <int> Q1) {
queue <int> Q = Q1;
while (!Q.empty()){
cout "\t" << Q.front();
Q.pop();
}
cout "\n" ;
}
int main() {
int i = 1;
queue <int> qd;
while (i < 5){
qd.push(i);
i++;
}
cout << "Queue: \n";
display(qd);
cout << "Popping an element from the queue.. \n";
qd.pop();
display(qd);
return 0;
}
Output
Queue: 1 2 3 4 Popping an element from the queue.. 2 3 4
Priority queue
In priority queue, the elements are placed in decreasing order
of their values and the first element represents the largest of all the inserted elements.
Syntax:
priority_queue <data_type> priority_queue_name;
Some of the functions offered by Priority queue:
priority_queue.empty()
: Checks whether the queue is empty or not.priority_queue.top()
: It returns the top element from the queue.priority_queue.pop()
: It deletes the first element from the queuepriority_queue.push(element)
: It inserts the element at the end of the queue.priority_queue.swap()
: It swaps the elements of one priority queue with another of the similar data type and size.priority_queue.size()
: It returns the number of elements present in the priority queue.
Example
#include <iostream>
#include <queue>
using namespace std;
void display(priority_queue <int> PQ) {
priority_queue <int> p = PQ;
while (!p.empty()){
cout "\t" << p.top();
p.pop();
}
cout "\n" ;
}
int main() {
int i = 1;
priority_queue <int> PQ;
while (i < 5){
PQ.push(i*10);
i++;
}
cout << "The Priority queue: \n";
display(PQ);
cout << "The Priority_queue.top() function: \n" << PQ.top();
cout << "The Priority_queue.pop() function: \n";
PQ.pop();
display(PQ);
return 0;
}
Output
The priority queue: 40 30 20 10 The priority_queue.top() function: 40 The priority_queue.pop() function: 30 20 10
Stack
Stack follows the Last-In-First-Out (LIFO) fashion. The items are inserted at one end of the stack and an item is deleted from the same end of the stack.
Syntax:
stack <data_type> stack_name;
Functionalities served by Stack are as follows:
stack.push(element)
: It inserts an element to the top of the stack.stack.pop()
: It deletes an element present at the top of the stack.stack.empty()
: It checks whether the stack is empty or not.stack.top()
: It returns the element present at the top of the stack.
Example
#include <bits/std++.h>
using namespace std;
void display(stack <int> S) {
while (!S.empty()){
cout "\t" << S.top();
S.pop();
}
cout "\n" ;
}
int main() {
stack <int> S;
s.push(1);
s.push(0);
s.push(2);
s.push(6);
cout << "The stack is: \n";
display(s);
cout << "\nThe top element of the stack: \n" << s.top();
cout << "\nStack after removing the top element from the stack: \n";
s.pop();
display(s);
return 0;
}
Output
The stack is : 6 2 0 1 The top element of the stack: 6 Stack after removing the top element from the stack: 2 0 1
Unordered Associative Containers
Unordered Associative Containers provides sorted
and unordered
data structures that can be used for efficient searching operations.
- unordered_set: A
hash table
is used to build and implement the unordered_set wherein the keys are hashed into the indices in order to randomize the insertion operation. The keys can be stored in any random order in an unordered_set. - unordered_multiset: It works in a similar fashion as that of the unordered_set. In
unordered_multiset,
duplicate items
can be stored. - unordered_map: It works like a map data structure i.e. has
key-value pair
associated with it. In unordered_map, the keys can be stored in any random order. - unordered_multimap: It works like multimap, but does allow storage of the
duplicate key-value pairs.
2. Algorithms in Standard Template Library
Standard Template Library provides us with different generic algorithms. These algorithms contain built in generic functions which can be directly accessed in the program.
The Algorithm and its functions can be accessed with the help of Iterators
only.
Types of Algorithms offered by Standard Template Library:
1. Sorting Algorithms
2. Search Algorithms
3. Non-modifying Algorithm
4. Modifying Algorithms
5. Numeric Algorithm
6. Minimum and Maximum operations
Sorting Algorithm in Standard Template Library
Standard Template Library provides built-in sort()
method to sort the elements in a particular data structure.
Internally, it uses a combination of Quick Sort, Heap Sort, and Insertion Sort to sort the elements.
Syntax:
sort(starting index, end_element_index)
Example
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int arr[5] = {10, 50, 0, -1, 48};
cout << "\nArray before sorting: \n";
for (int i = 0; i < 5; ++i){
cout << arr[i] << " ";
}
sort (arr, arr+5);
cout << "\nArray after sorting: \n";
for (int i = 0; i < 5; ++i){
cout << arr[i] << " ";
}
return 0;
}
Output
Array before sorting: 10 50 0 -1 48 Array after sorting: -1 0 10 48 50
3. Iterators in Standard Template Library
Iterators are basically used to point or refer to a particular memory location of the element. They point at the containers and help them manipulate the elements in an efficient manner.
Following are some of the commonly used functions offered by Iterators in Standard Template Library:
iterator.begin()
: It returns the reference to the first element of the container.iterator.end()
: It returns the reference to the last element of the container.iterator.prev(iterator_name, index)
: It returns the position of the new iterator that would point to the element before the specified index value in the parameter.iterator.next(iterator_name, index)
: It returns the position of the new iterator that would point to the element after the specified index value in the parameter.iterator.advance(index)
: It increments the iterator’s position to the specified index value.
Example
#include <iostream>
#include <iterator>
using namespace std;
int main() {
list <int> lst = {10, 50, 70, 45, 36};
list <int> :: iterator itr;
cout << "\nInput List: \n";
for (itr = lst.begin(); itr != lst.end(); itr++){
cout << *ltr << " ";
}
list <int> :: iterator it = lst.begin();
advance(it, 1);
cout << "\nThe position of iterator after advance(): \n";
cout << *it << " ";
return 0;
}
In the above snippet of code, advance(it, 1)
points the iterator to the element at the index value = 1.
Output
Input List: 10 50 70 45 36 The position of iterator after advancing is : 50
Conslusion
We hope that this tutorial helped you develop better understanding of the concept of Standard Template Library in C++.
we have understood the Standard Template Library and it components in a detailed manner.
Keep Learning : )