OOP Unit 6 Notes
OOP Unit 6 Notes
Unit –VI
Standard Template Library (STL)
1. STL
The Standard Template Library (STL) in C++ is a powerful library of pre-defined classes
and functions designed to simplify programming tasks. These components provide ready-made
code for handling algorithms, data structures, and operations, regardless of the data type.
For example, sorting elements in a list is a generalized operation. The same sorting algorithm
can be applied to integers, floats, or any other data type. STL leverages generic programming
to achieve this flexibility, enabling programmers to reuse code for various data types.
It is a set of template classes that implement common algorithms and data structures.
It is defined using generic programming, making it applicable to nearly all data types.
STL provides components to focus on what operations can be performed, rather than
on the underlying data type.
STL offers a vast set of template classes and functions to perform a variety of tasks.
Its generic programming approach allows these classes and functions to operate on
different types of data.
STL simplifies complex programming tasks, reducing both development time and
effort.
The STL consists of three core components: Containers, Algorithms, and Iterators.
1. Containers
Sequence Containers: Maintain the order of elements (e.g., vector, list, deque).
Unordered Associative Containers: Use hash tables for faster access but don't
maintain order (e.g., unordered_set, unordered_map).
2. Algorithms
o The STL provides a wide range of pre-defined algorithms that can be applied to
containers, regardless of their type.
3. Iterators
o Iterators are objects that act like pointers to elements within a container.
o They serve as a bridge between containers and algorithms, enabling seamless traversal
and manipulation of container contents.
o Using iterators, you can cycle through the elements of a container in a specific order.
Code Reusability: Generic programming allows the same algorithms to work with
various data types.
3|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
1.3 Containers
Containers are objects designed to hold collections of other objects, offering functionality to
store, access, and manipulate data.
Types of Containers
1. Sequence Containers
Description: These containers store elements in a linear order, where new elements are
added to the end of the collection.
Characteristics:
o Commonly used for dynamic arrays, linked lists, and double-ended queues.
2. Associative Containers
Description: These containers store elements in a sorted order, where the position of
an element is determined by its value.
Characteristics:
o Efficient for tasks requiring frequent lookups, such as dictionaries and sets.
Characteristics:
o Use hash tables for internal organization, enabling faster access than sorted
associative containers.
o Suitable for applications where order is not important but fast lookups are essential.
Container Adaptors
5|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
They allow developers to use underlying containers (like vector or deque) with additional
constraints, adapting their functionality to meet specific requirements.
1. stack:
o Operates by pushing elements onto the top and popping them off the top.
2. queue:
o Operates by adding elements to the back and removing them from the front.
3. priority_queue:
Containers are collections of elements that provide common functions to manipulate and
organize data.
1. Array
Operations on Array:
6|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
#include <iostream>
#include <array> // For std::array
using namespace std;
int main() {
// Initializing an array of fixed size
array<int, 5> arr = {10, 20, 30, 40, 50};
Vectors are the most commonly used containers in STL. They are sequence containers
representing dynamic arrays that can change their size as needed. When the number of elements
exceeds its current capacity, the vector dynamically allocates additional memory to
accommodate new elements.
Advantages:
1. Automatically resizes, allowing the user to add elements without worrying about the
container size.
Disadvantage:
vector<int> c(5, 0): Creates a 5-element vector of int with all elements initialized to 0.
1. Iterator-Related Functions
8|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
rend(): Returns a reverse iterator to the position before the first element.
cend(): Returns a constant iterator to the position after the last element.
crend(): Returns a constant reverse iterator to the position before the first element.
2. Capacity-Related Functions
max_size(): Returns the maximum number of elements the vector can hold.
#include <iostream>
9|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
#include <vector>
using namespace std;
int main() {
// Create a vector and add elements
vector<int> vec = {1, 2, 3, 4, 5};
// Modify vector
vec.push_back(6);
cout << "\nAfter push_back(6), size: " << vec.size() << ",
Capacity: " << vec.capacity();
vec.pop_back();
cout << "\nAfter pop_back(), size: " << vec.size();
Output:
Vector elements: 1 2 3 4 5
Element at index 2 (using at): 3
Element at index 3 (using []): 4
Size: 5, Capacity: 5
After push_back(6), size: 6, Capacity: 10
After pop_back(), size: 5
Front: 1, Back: 5
3. List
Lists are sequential containers implemented as doubly-linked lists. They allow insertion and
deletion operations anywhere within the sequence and support iteration in both directions.
Advantages:
2. Performs better for sorting and algorithms requiring intensive element movement.
Drawbacks:
1. No Direct Access: To access the nth element, iteration is required from the current
position to the desired element.
1. Element Access:
3. Modifiers:
o assign(): Replaces current elements with new ones and resizes the list.
o max_size(): Returns the maximum number of elements the list can hold.
5. Iterators:
o end(): Returns an iterator pointing to the theoretical element after the last one.
#include <iostream>
#include <list>
using namespace std;
int main() {
// Initializing a list
list<int> lst = {10, 20, 30, 40, 50};
// Using reverse
lst.reverse();
cout << "After reverse(): ";
for (int x : lst)
cout << x << " ";
cout << endl;
// Using sort
lst.sort();
cout << "After sort(): ";
for (int x : lst)
cout << x << " ";
cout << endl;
13 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
return 0;
}
4. Deque
A Deque (Double-Ended Queue) is a sequence container with dynamic sizes that allows
insertion and deletion at both ends (front and back).
Deques are more efficient for insertion and deletion of elements compared to vectors.
They are often used to implement data structures like queues and stacks.
Characteristics of Deque:
2. Similar to queues but supports operations at both the front and back.
Advantages:
Drawbacks:
o at(pos) – Accesses the element at the specified position (with bounds checking).
3. Iterators
4. Capacity
o max_size() – Returns the maximum number of elements the deque can hold.
5. Modifiers
o assign(n, value) – Replaces the contents with n elements of the given value.
#include <iostream>
#include <deque>
15 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
int main() {
deque<int> dq;
// Accessing elements
cout << "Front element: " << dq.front() << endl;
cout << "Back element: " << dq.back() << endl;
dq.erase(dq.begin());
cout << "Deque after erase: ";
for (int x : dq)
cout << x << " ";
cout << endl;
A stack is a container adapter designed to operate in LIFO (Last In, First Out) order, meaning
elements are added and removed only from one end, called the top of the stack.
Stacks internally use other standard containers like vector or deque for their implementation.
Features of Stack:
Operates only at the top, making it highly efficient for operations like function calls,
undo mechanisms, etc.
Ideal for solving problems such as expression evaluation, parenthesis balancing, and
DFS in graphs.
#include <iostream>
#include <stack>
using namespace std;
int main() {
stack<int> s;
cout << "Initial stack size: " << s.size() << endl;
cout << "After pop, new top element: " << s.top() << endl;
cout << "Stack is now empty. Size: " << s.size() << endl;
return 0;
}
Output:
Initial stack size: 3
Top element: 30
After pop, new top element: 20
Is the stack empty? No
Popped element: 20
Popped element: 10
Stack is now empty. Size: 0
6. Set
Sets are associative containers that store unique elements in a specific order. They
automatically sort their elements using an internal sorting algorithm.
You can insert and remove values in the set, but all elements in a set are unique, meaning
duplicates are not allowed.
2. end(): Returns an iterator pointing to the theoretical element that follows the last
element in the set.
4. max_size(): Returns the maximum number of elements the set can hold (dependent
on system and implementation).
5. empty(): Returns whether the set is empty (true if empty, false otherwise).
6. insert(const g): Adds a new element g to the set. If g already exists, the insertion
is ignored.
7. lower_bound(const g): Returns an iterator pointing to the first element that is not
less than g, or the first element that is equivalent to g or greater.
#include <iostream>
#include <set>
using namespace std;
int main() {
// Creating a set of integers
set<int> s;
if (lb != s.end()) {
cout << "Lower bound of " << x << " is: " << *lb << endl;
} else {
cout << "Lower bound of " << x << " does not exist." << endl;
}
if (ub != s.end()) {
cout << "Upper bound of " << x << " is: " << *ub << endl;
} else {
cout << "Upper bound of " << x << " does not exist." << endl;
}
return 0;
21 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
}
Output:
Elements in the set: 5 10 15 20 25
Is the set empty? No
Size of the set: 5
Lower bound of 15 is: 15
Upper bound of 15 is: 20
7. Map
Maps are associative (ordered) containers that store key-value pairs, where each key is unique
and used to sort the elements in the container. The value is associated with its corresponding
key.
In a map, the keys are used to uniquely identify elements, and the values store the content
corresponding to those keys. Maps automatically sort elements by the key.
Example: In a map, a pair like "name" = "Rohan" represents a key-value pair, where
"name" is the key and "Rohan" is the value.
Methods of Map
2. end(): Returns an iterator to the theoretical element that follows the last element in the
map.
4. max_size(): Returns the maximum number of elements the map can hold.
5. empty(): Returns whether the map is empty. Returns true if the map is empty, false
otherwise.
6. insert(key, value): Adds a new element to the map with the specified key and value.
If the key already exists, it does not insert the duplicate key.
8. erase(const key): Removes the element associated with the specified key from the map.
22 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
#include <iostream>
#include <map>
using namespace std;
int main() {
// Create a map where key is a string and value is an integer
map<string, int> myMap;
return 0;
}
Output:
Elements in the map:
Alice : 30
Bob : 25
Charlie : 35
Age of Bob: 25
2. Algorithms
The Standard Template Library (STL) offers over 80 generic algorithms that can operate on
a wide variety of containers and ranges. These algorithms are stand-alone functions, not
24 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
member functions of container classes, which means they can operate on both C-style arrays
and STL containers. The <algorithm> header defines these algorithms, and they are designed
to be used with iterators to apply operations on container elements.
Non-Modifying Sequence Operations: These algorithms do not modify the container but
allow testing and searching operations:
13. std::mismatch: Returns the first position where two ranges differ.
Modifying Sequence Operations: These algorithms modify the elements in the container
Partition Operations: These algorithms partition ranges into groups based on a condition
7. std::nth_element: Reorders the elements in a range such that the n-th element is in
its correct position.
Binary Search Operations (on sorted ranges): These algorithms perform binary search
operations:
1. std::lower_bound: Returns the iterator to the first element not less than the given
value.
27 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
2. std::upper_bound: Returns the iterator to the first element greater than the given
value.
Merge Operations (on sorted ranges): These algorithms are used to merge sorted ranges
Heap Operations
6. std::is_heap_until: Finds the first element not satisfying the heap property.
Min/Max Operations
Other Operations
Sorting is one of the most fundamental operations on data, which arranges elements in a
particular order (typically increasing or decreasing). C++ provides a built-in sorting function
in the STL called sort(), which is highly efficient.
The sort() function internally uses IntroSort, a hybrid algorithm combining QuickSort,
HeapSort, and InsertionSort. By default, it uses QuickSort, but if QuickSort’s partitioning
becomes inefficient (e.g., it takes more than NlogN time), the algorithm switches to HeapSort.
For very small arrays, it switches to InsertionSort.
Prototype:
sort(startaddress, endaddress);
Stable Sort
A stable sort ensures that the relative order of equal elements is preserved. The
stable_sort() function guarantees that if two elements are equivalent, their order in the
original container will be retained after sorting.
29 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
Prototype:
Example:
});
In the above example, stable_sort() ensures that the relative order of equal-length strings
(like "apple") is preserved.
Partial Sort
The partial_sort() function is used when you want to sort only a portion of the data.
Unlike sort(), which sorts the entire range, partial_sort() sorts only the first part,
leaving the remaining elements in an unspecified order.
Here, only the first three elements are sorted in ascending order, while the rest are left unsorted.
Heap Sort
The heap_sort() function is an STL algorithm used to sort elements in a heap range. It works
in ascending order and requires that the elements are arranged in a heap structure before sorting.
Two Versions:
30 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
cmpfn is a custom comparison function or function object that defines the sorting order.
The sort_heap() function does not return any value (it operates in place).
Example:
#include <iostream>
#include <vector>
#include <algorithm> // For std::sort
int main() {
// Initialize a vector of integers
std::vector<int> vec = {12, 7, 9, 3, 5, 15, 8};
std::sort(vec.begin(), vec.end());
return 0;
}
2.2 Searching Algorithms
Efficient information retrieval is crucial as it saves time and ensures smooth execution of
subsequent tasks. Searching algorithms are designed to quickly locate a specific piece of
information within a dataset. Among these, Binary Search stands out as one of the most
efficient techniques.
Binary Search
Binary Search is a widely used algorithm for finding an element in a sorted array. It operates
using the divide-and-conquer approach, repeatedly halving the search space until the target is
found or the search space is exhausted.
2. Comparison: The middle element of the array is compared to the target value:
o If the middle element matches the target, the search is successful, and the index
of the middle element is returned.
o If the middle element is greater than the target, the search is confined to the left
sub-array.
o If the middle element is smaller than the target, the search continues in the right
sub-array.
32 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
3. The process repeats until the target is found or the array can no longer be divided.
Function Prototype:
startaddress: The address of the first element in the array (or container).
endaddress: The address of the next position after the last element in the array.
Time Efficiency: Operates in O(log N), making it much faster than linear search for
large datasets.
Limitations:
The array must be sorted beforehand, which may add preprocessing overhead if the data
is unsorted.
Not suitable for unsorted or dynamically changing data without frequent re-sorting.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
vector<int> arr = {1, 3, 5, 7, 9, 11, 13};
return 0;
}
2.3 min-max Algorithms
C++ has defined some functions to get smallest and largest elements among 2 or in a container
using different functions. But there are also functions that are used to get both smallest and
largest element using a single function, “minmax()” function achieves this task for use. This
function is defined in “algorithm” header file.
1. minmax(a, b): This function returns a pair, in which 1st element is of minimum of the two
elements and the 2nd element is maximum of 2 elements.
Example:
#include <iostream>
#include <algorithm> // For minmax
#include <vector>
int main() {
// Example array
vector<int> arr = {42, 15, 78, 4, 56, 19};
// Using minmax_element
auto result = minmax_element(arr.begin(), arr.end());
34 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.
return 0;
}
Output:
Array: 42 15 78 4 56 19
Minimum value: 4
Maximum value: 78
3. Iterators
Iterators are objects that act as pointers to elements within STL containers, allowing access and
traversal of data. They enable cycling through container elements efficiently, reducing
complexity and execution time in programs. Iterators are versatile and can be incremented or
decremented to move through a container's elements.
Operations of Iterators
2. end(): Returns an iterator pointing to the position after the last element of the
container.
Types of Iterators
1. Input Iterator:
2. Output Iterator:
o Operators: ++, =
3. Forward Iterator:
4. Bidirectional Iterator:
o Supports all bidirectional iterator features and allows direct access to elements
using addition (+) or subtraction (-).
o Operators: ++, --, +, -, [], ==, !=, <, >, <=, >=
Iterator Characteristics
Providers of Iterators
Advantages of Iterators
1. Ease of Programming: Using iterators is simpler than the subscript operator ([]) as
they eliminate the need to track element counts.
2. Code Reusability: Iterators enable reusability; for example, they work with both vector
and list, unlike the subscript operator.
3. Dynamic Processing: Iterators facilitate dynamic addition and deletion of data within
containers.
Disadvantages of Iterators
Example:
#include <iostream>
#include <vector>
#include <list>
#include <iterator> // For advance, next, prev, and inserter
int main() {
// Example with vector
vector<int> vec = {10, 20, 30, 40, 50};
cout << "Vector elements using iterators: ";
for (vector<int>::iterator it = vec.begin(); it != vec.end();
++it) {
cout << *it << " ";
}
cout << endl;
// Using advance
advance(it, 2); // Move iterator to the 3rd position
cout << "Using advance to move to 3rd element in list: " << *it
<< endl;