Table of Contents
What is STL?
The Standard Template Library (STL) is a set of 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 STL has four components :
- Algorithms
- Containers
- Functions
- Iterators
At the core of the C++ Standard Template Library are following three well-structured components −
Sr.No | Component | Description |
---|---|---|
1 | Containers | Containers are used to manage collections of objects of a certain kind. There are several different types of containers like deque, list, vector, map etc. |
2 | Algorithms | Algorithms act on containers. They provide the means by which you will perform initialization, sorting, searching, and transforming of the contents of containers. |
3 | Iterators | Iterators are used to step through the elements of collections of objects. These collections may be containers or subsets of containers. |
4 | Function | The STL includes classes that overload the function call operator. Instances of such classes are called function objects or functors. Functors allow the working of the associated function to be customized with the help of parameters to be passed. |
What is Containers?
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.
Sequence Containers
It implement data structures which can be accessed in a sequential manner.
Vector : Vectors are same as dynamic arrays with the ability to resize itself automatically when an element is inserted or deleted, with their storage being handled automatically by the container.
- Vector elements are placed in contiguous storage so that they can be accessed and traversed using iterators. In vectors, data is inserted at the end.
- Inserting at the end takes differential time, as sometimes there may be a need of extending the array.
- Removing the last element takes only constant time because no resizing happens. Inserting and erasing at the beginning or in the middle is linear in time.
// C++ program to illustrate the
// iterators in vector
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> g1;
for (int i = 1; i <= 5; i++)
g1.push_back(i);
cout << "Output of begin and end: ";
for (auto i = g1.begin(); i != g1.end(); ++i)
cout << *i << " ";
cout << "\nOutput of cbegin and cend: ";
for (auto i = g1.cbegin(); i != g1.cend(); ++i)
cout << *i << " ";
cout << "\nOutput of rbegin and rend: ";
for (auto ir = g1.rbegin(); ir != g1.rend(); ++ir)
cout << *ir << " ";
cout << "\nOutput of crbegin and crend : ";
for (auto ir = g1.crbegin(); ir != g1.crend(); ++ir)
cout << *ir << " ";
return 0;
}
Output :
Output of begin and end: 1 2 3 4 5
Output of cbegin and cend: 1 2 3 4 5
Output of rbegin and rend: 5 4 3 2 1
Output of crbegin and crend : 5 4 3 2 1
2.List : Lists are sequence containers that allow non-contiguous memory allocation.
- As compared to vector, list has slow traversal, but once a position has been found, insertion and deletion are quick.
- Normally, when we say a List, we talk about doubly linked list.
- For implementing a singly linked list, we use forward list.
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
//function for printing the elements in a list
void showlist(list <int> g)
{
list <int> :: iterator it;
for(it = g.begin(); it != g.end(); ++it)
cout << '\t' << *it;
cout << '\n';
}
int main()
{
list <int> gqlist1, gqlist2;
for (int i = 0; i < 10; ++i)
{
gqlist1.push_back(i * 2);
gqlist2.push_front(i * 3);
}
cout << "\nList 1 (gqlist1) is : ";
showlist(gqlist1);
cout << "\nList 2 (gqlist2) is : ";
showlist(gqlist2);
cout << "\ngqlist1.front() : " << gqlist1.front();
cout << "\ngqlist1.back() : " << gqlist1.back();
cout << "\ngqlist1.pop_front() : ";
gqlist1.pop_front();
showlist(gqlist1);
cout << "\ngqlist2.pop_back() : ";
gqlist2.pop_back();
showlist(gqlist2);
cout << "\ngqlist1.reverse() : ";
gqlist1.reverse();
showlist(gqlist1);
cout << "\ngqlist2.sort(): ";
gqlist2.sort();
showlist(gqlist2);
return 0;
}
Output :
List 1 (gqlist1) is : 0 2 4 6
8 10 12 14 16 18
List 2 (gqlist2) is : 27 24 21 18
15 12 9 6 3 0
gqlist1.front() : 0
gqlist1.back() : 18
gqlist1.pop_front() : 2 4 6 8
10 12 14 16 18
gqlist2.pop_back() : 27 24 21 18
15 12 9 6 3
gqlist1.reverse() : 18 16 14 12
10 8 6 4 2
gqlist2.sort(): 3 6 9 12
15 18 21 24 27
Deque : double ended queues are sequence containers with the feature of expansion and contraction on both the ends.
- They are similar to vectors, but are more efficient in case of insertion and deletion of elements. Unlike vectors, contiguous storage allocation may not be guaranteed.
- Double Ended Queues are basically an implementation of the data structure double ended queue.
- A queue data structure allows insertion only at the end and deletion from the front. This is like a queue in real life, wherein people are removed from the front and added at the back.
- Double ended queues are a special case of queues where insertion and deletion operations are possible at both the ends.
- The functions for deque are same as vector, with an addition of push and pop operations for both front and back.
#include <iostream>
#include <deque>
using namespace std;
void showdq(deque <int> g)
{
deque <int> :: iterator it;
for (it = g.begin(); it != g.end(); ++it)
cout << '\t' << *it;
cout << '\n';
}
int main()
{
deque <int> gquiz;
gquiz.push_back(10);
gquiz.push_front(20);
gquiz.push_back(30);
gquiz.push_front(15);
cout << "The deque gquiz is : ";
showdq(gquiz);
cout << "\ngquiz.size() : " << gquiz.size();
cout << "\ngquiz.max_size() : " << gquiz.max_size();
cout << "\ngquiz.at(2) : " << gquiz.at(2);
cout << "\ngquiz.front() : " << gquiz.front();
cout << "\ngquiz.back() : " << gquiz.back();
cout << "\ngquiz.pop_front() : ";
gquiz.pop_front();
showdq(gquiz);
cout << "\ngquiz.pop_back() : ";
gquiz.pop_back();
showdq(gquiz);
return 0;
}
Output :
The deque gquiz is : 15 20 10 30
gquiz.size() : 4
gquiz.max_size() : 4611686018427387903
gquiz.at(2) : 10
gquiz.front() : 15
gquiz.back() : 30
gquiz.pop_front() : 20 10 30
gquiz.pop_back() : 20 10
Array : The introduction of array class from C++11 has offered a better alternative for C-style arrays. The advantages of array class over C-style array are :-
- Array classes knows its own size, whereas C-style arrays lack this property. So when passing to functions, we don’t need to pass size of Array as a separate parameter.
- With C-style array there is more risk of array being decayed into a pointer. Array classes don’t decay into pointers
- Array classes are generally more efficient, light-weight and reliable than C-style arrays.
// C++ code to demonstrate working of array,
// to() and get()
#include<iostream>
#include<array> // for array, at()
#include<tuple> // for get()
using namespace std;
int main()
{
// Initializing the array elements
array<int,6> ar = {1, 2, 3, 4, 5, 6};
// Printing array elements using at()
cout << "The array elemets are (using at()) : ";
for ( int i=0; i<6; i++)
cout << ar.at(i) << " ";
cout << endl;
// Printing array elements using get()
cout << "The array elemets are (using get()) : ";
cout << get<0>(ar) << " " << get<1>(ar) << " ";
cout << get<2>(ar) << " " << get<3>(ar) << " ";
cout << get<4>(ar) << " " << get<5>(ar) << " ";
cout << endl;
// Printing array elements using operator[]
cout << "The array elements are (using operator[]) : ";
for ( int i=0; i<6; i++)
cout << ar[i] << " ";
cout << endl;
return 0;
}
Output :
The array elemets are (using at()) : 1 2 3 4 5 6
The array elemets are (using get()) : 1 2 3 4 5 6
The array elements are (using operator[]) : 1 2 3 4 5 6