LIST in C++ STL

DESCRIPTION:

  • Doubly linked list that supports efficient insertion and deletion at any position.

  • Resembles a vector but with constant time complexity for insertions and deletions at any position.

  • Suitable for scenarios requiring frequent insertions and deletions without the need for random access.

  • Can be used as a dynamic list with automatic resizing.


ALL THE POSSIBLE WAYS TO DECLARE, INITIALIZE AND PRINTING LIST:

#include <iostream>
#include <list>
#include <string>

using namespace std;

int main() {
    // Declaration of an empty list of integers
    list<int> myList;

    // Declaration of a list of doubles
    list<double> doubleList;

    // Declaration of a list of strings
    list<string> stringList;

    // Initializing list with values using initializer list
    list<int> initializedList = {1, 2, 3, 4, 5};

    // Initializing list with a specific size and default value
    list<int> sizedList(5, 0); // List of size 5, all elements initialized to 0

    // Dynamic initialization using push_back
    list<int> dynamicList;
    dynamicList.push_back(10);
    dynamicList.push_back(20);
    dynamicList.push_back(30);

    // Adding elements to the front of the list using push_front
    dynamicList.push_front(5);
    dynamicList.push_front(15);

    // Copying from another list
    list<int> sourceList = {1, 2, 3, 4, 5};
    list<int> copiedList(sourceList); // Copy constructor

    // Printing list using for loop and list.begin()
    cout << "Sized List (list.begin()): ";
    for (auto it = sizedList.begin(); it != sizedList.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // Printing list using for loop and iterator
    cout << "Dynamic List (iterator): ";
    for (list<int>::iterator it = dynamicList.begin(); it != dynamicList.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // Printing list using for loop and auto keyword
    cout << "Copied List (auto): ";
    for (auto element : copiedList) {
        cout << element << " ";
    }
    cout << endl;

    return 0;
}

OUTPUT:

Sized List (list.begin()): 0 0 0 0 0 
Dynamic List (iterator): 15 5 10 20 30 
Copied List (auto): 1 2 3 4 5

MEMBER FUNCTIONS:

  1. Front:

    • Works: Returns a reference to the first element.

    • Syntax: myList.front()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        int firstElement = myList.front();
      
  2. Back:

    • Works: Returns a reference to the last element.

    • Syntax: myList.back()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        int lastElement = myList.back();
      
  3. At(), Data():

    • Works: There is no direct equivalent in std::list because it does not provide direct access to elements via pointers. You would typically use iterators for element access in a std::list.
  4. Size:

    • Works: Returns the number of elements.

    • Syntax: myList.size()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        std::size_t listSize = myList.size();
      
  5. Max Size:

    • Works: Returns the maximum number of elements.

    • Syntax: myList.max_size()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        std::size_t maxListSize = myList.max_size();
      
  6. Empty:

    • Works: Returns whether the container is empty.

    • Syntax: myList.empty()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        bool isListEmpty = myList.empty();
      
  7. Begin(), End(), Rbegin(), Rend():

    • Works: Iterator functions. For std::list, there is no direct equivalent of at(). Instead, you use iterators for accessing elements.

    • Syntax: myList.begin(), myList.end(), myList.rbegin(), myList.rend()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        auto beginIterator = myList.begin();
        auto endIterator = myList.end();
        auto rbeginIterator = myList.rbegin();
        auto rendIterator = myList.rend();
      

CODE:

#include <iostream>
#include <list>

using namespace std;

int main() {
    // Declaration of a list of integers
    list<int> myList = {1, 2, 3, 4, 5};

    // Access element at position using iterators
    list<int>::iterator it = next(myList.begin(), 2);  // Move iterator to position 2
    int elementAtPositionG = *it;
    cout << "Element at position 2: " << elementAtPositionG << endl;

    // front()
    int firstElement = myList.front();
    cout << "First element: " << firstElement << endl;

    // back()
    int lastElement = myList.back();
    cout << "Last element: " << lastElement << endl;

    // size()
    size_t listSize = myList.size();
    cout << "Size of the list: " << listSize << endl;

    // max_size()
    size_t maxListSize = myList.max_size();
    cout << "Maximum size of the list: " << maxListSize << endl;

    // empty()
    bool isListEmpty = myList.empty();
    cout << "Is the list empty? " << (isListEmpty ? "Yes" : "No") << endl;

    // begin(), end(), rbegin(), rend()
    auto beginIterator = myList.begin();
    auto endIterator = myList.end();
    auto rbeginIterator = myList.rbegin();
    auto rendIterator = myList.rend();

    // Print elements using iterators
    cout << "Elements using iterators: ";
    for (auto it = beginIterator; it != endIterator; ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // Print elements in reverse using reverse iterators
    cout << "Elements in reverse: ";
    for (auto rit = rbeginIterator; rit != rendIterator; ++rit) {
        cout << *rit << " ";
    }
    cout << endl;

    return 0;
}

OUTPUT:

Element at position 2: 3
First element: 1
Last element: 5
Size of the list: 5
Maximum size of the list: 9223372036854775807
Is the list empty? No
Elements using iterators: 1 2 3 4 5 
Elements in reverse: 5 4 3 2 1

MODIFIERS:

  1. Assign:

    • Works: Assigns new values to list elements.

    • Syntax: myList.assign(first_iterator, last_iterator)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        vector<int> newValues = {6, 7, 8};
        myList.assign(newValues.begin(), newValues.end());
      
  2. Push Back:

    • Works: Adds elements to the end.

    • Syntax: myList.push_back(value)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.push_back(6);
      
  3. Push Front:

    • Works: Adds elements to the beginning.

    • Syntax: myList.push_front(value)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.push_front(3);
      
  4. Pop Back:

    • Works: Removes the last element.

    • Syntax: myList.pop_back()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.pop_back();
      
  5. Pop Front:

    • Works: Removes the first element.

    • Syntax: myList.pop_front()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.pop_front();
      
  6. Insert:

    • Works: Inserts new elements at a specified position.

    • Syntax: myList.insert(iterator_position, value)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.insert(myList.begin(), 8);
      
  7. Erase:

    • Works: Removes elements from a specified position or range.

    • Syntax: myList.erase(position)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.erase(myList.begin());
      
  8. Swap:

    • Works: Swaps contents with another list.

    • Syntax: myList.swap(otherList)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        list<int> anotherList = {6, 7, 8};
        myList.swap(anotherList);
      
  9. Resize:

    • Works: Resizes the container to contain 'n' elements.

    • Syntax: myList.resize(n)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.resize(7);
      
  10. Clear:

    • Works: Removes all elements.

    • Syntax: myList.clear()

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.clear();
      
  11. Emplace:

    • Works: Inserts a new element at a position.

    • Syntax: myList.emplace(iterator_position, args)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.emplace(myList.begin(), 10);
      
  12. Emplace Back:

    • Works: Inserts a new element at the end.

    • Syntax: myList.emplace_back(args)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.emplace_back(12);
      
  13. Emplace Front:

    • Works: Inserts a new element at the beginning.

    • Syntax: myList.emplace_front(args)

    • Example:

        list<int> myList = {1, 2, 3, 4, 5};
        myList.emplace_front(5);
      

CODE:

#include <iostream>
#include <list>

using namespace std;

int main() {
    // Initialize a list
    list<int> myList = {1, 2, 3, 4, 5};

    // Print the initial list
    cout << "Initial List: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // assign()
    myList.assign({10, 20, 30});
    cout << "After Assign: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // push_back()
    myList.push_back(40);
    cout << "After Push Back: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // push_front()
    myList.push_front(5);
    cout << "After Push Front: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // pop_back()
    myList.pop_back();
    cout << "After Pop Back: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // pop_front()
    myList.pop_front();
    cout << "After Pop Front: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // insert()
    auto it = myList.begin();
    ++it;
    myList.insert(it, 99);
    cout << "After Insert: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // erase()
    auto eraseIt = myList.begin();
    ++eraseIt;
    myList.erase(eraseIt);
    cout << "After Erase: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // swap()
    list<int> anotherList = {100, 200, 300};
    myList.swap(anotherList);
    cout << "After Swap - myList: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << "\nAfter Swap - anotherList: ";
    for (const auto& element : anotherList) {
        cout << element << " ";
    }
    cout << endl;

    // resize()
    myList.resize(3);
    cout << "After Resize: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // clear()
    myList.clear();
    cout << "After Clear: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // emplace()
    myList.emplace(myList.begin(), 99);
    cout << "After Emplace: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // emplace_back()
    myList.emplace_back(88);
    cout << "After Emplace Back: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // emplace_front()
    myList.emplace_front(77);
    cout << "After Emplace Front: ";
    for (const auto& element : myList) {
        cout << element << " ";
    }
    cout << endl;

    return 0;
}

OUTPUT:

Initial List: 1 2 3 4 5 
After Assign: 10 20 30 
After Push Back: 10 20 30 40 
After Push Front: 5 10 20 30 40 
After Pop Back: 5 10 20 30 
After Pop Front: 10 20 30 
After Insert: 10 99 20 30 
After Erase: 10 20 30 
After Swap - myList: 100 200 300 
After Swap - anotherList: 10 20 30 
After Resize: 100 200 300 
After Clear: 
After Emplace: 99 
After Emplace Back: 99 88 
After Emplace Front: 77 99 88

ALGORITHMS

ALGORITHMS DIRECTLY APPLICABLE TO LIST:

  1. Binary Search (binary_search):

    • Works: Checks if an element exists in a sorted range.

    • Syntax: binary_search(begin, end, value)

    • Example:

        bool exists = binary_search(myList.begin(), myList.end(), 5);
      
  2. Equal Range (equal_range):

    • Works: Finds the range of elements matching a specific value.

    • Syntax: equal_range(begin, end, value)

    • Example:

        auto range = equal_range(myList.begin(), myList.end(), 5);
      
  3. Inplace Merge (merge):

    • Works: Merges two sorted ranges into one sorted range in-place.

    • Syntax: merge(first_begin, first_end, second_begin, second_end)

    • Example:

        merge(myList.begin(), myList.end(), secondList.begin(), secondList.end(), myList.begin());
      
  4. Lower Bound (lower_bound):

    • Works: Finds the first position where an element can be inserted without disrupting the sorted order.

    • Syntax: lower_bound(begin, end, value)

    • Example:

        auto insertPos = lower_bound(myList.begin(), myList.end(), 5);
      
  5. Merge (merge):

    • Works: Merges two sorted ranges into a new sorted range.

    • Syntax: merge(first_begin, first_end, second_begin, second_end, destination_begin)

    • Example:

        merge(myList.begin(), myList.end(), thirdList.begin(), thirdList.end(), myList.begin());
      
  6. Partition (partition):

    • Works: Rearranges elements in a range based on a given condition.

    • Syntax: partition(begin, end, condition)

    • Example:

        partition(myList.begin(), myList.end(), [](int x) { return x % 2 == 0; });
      
  7. Sort (sort):

    • Works: Sorts elements in a range.

    • Syntax: sort(begin, end)

    • Example:

        sort(myList.begin(), myList.end());
      
  8. Upper Bound (upper_bound):

    • Works: Finds the position where an element can be inserted after the last occurrence without disrupting the sorted order.

    • Syntax: upper_bound(begin, end, value)

    • Example:

        auto insertPos = upper_bound(myList.begin(), myList.end(), 5);
      
  9. Max (max):

    • Works: Returns the larger of two values.

    • Syntax: max(value1, value2)

    • Example:

        int larger = max(10, 5);
      
  10. Max Element (max_element):

    • Works: Finds the maximum element in a range.

    • Syntax: max_element(begin, end)

    • Example:

        auto maxElem = max_element(myList.begin(), myList.end());
      
  11. Min (min):

    • Works: Returns the smaller of two values.

    • Syntax: min(value1, value2)

    • Example:

        int smaller = min(10, 5);
      
  12. Min Element (min_element):

    • Works: Finds the minimum element in a range.

    • Syntax: min_element(begin, end)

    • Example:

        auto minElem = min_element(myList.begin(), myList.end());
      
  13. Accumulate (accumulate):

    • Works: Calculates the sum of elements in a range.

    • Syntax: accumulate(begin, end, initial_value)

    • Example:

        int sum = accumulate(myList.begin(), myList.end(), 0);
      
  14. Reverse (reverse):

    • Works: Reverses the order of elements in a range.

    • Syntax: reverse(begin, end)

    • Example:

        reverse(myList.begin(), myList.end());
      
  15. Unique (unique):

    • Works: Removes consecutive duplicate elements from a range.

    • Syntax: unique(begin, end)

    • Example:

        unique(myList.begin(), myList.end());
      
  16. Remove (remove):

    • Works: Removes elements equal to a specified value from a range.

    • Syntax: remove(begin, end, value)

    • Example:

        remove(myList.begin(), myList.end(), 5);
      
  17. Remove If (remove_if):

    • Works: Removes elements satisfying a given condition from a range.

    • Syntax: remove_if(begin, end, condition)

    • Example:

        remove_if(myList.begin(), myList.end(), [](int x) { return x % 2 == 0; });
      
  18. Splice (splice):

    • Works: Transfers elements from one list to another or within the same list.

    • Syntax: splice(position, source_list, [source_begin, source_end])

    • Example:

        myList.splice(splicePoint, anotherList);
      

CODE:

#include <iostream>
#include <list>
#include <algorithm>
#include <numeric>

using namespace std;

int main() {
    // Create lists for testing
    list<int> myList = {1, 2, 3, 4, 5, 5, 6};
    list<int> secondList = {7, 8, 9};
    list<int> thirdList = {10, 11, 12};

    // Binary Search (binary_search)
    bool exists = binary_search(myList.begin(), myList.end(), 5);
    cout << "Binary Search - Element 5 exists: " << (exists ? "Yes" : "No") << endl;

    // Equal Range (equal_range)
    auto range = equal_range(myList.begin(), myList.end(), 5);
    cout << "Equal Range - Range of elements matching 5: [" << *range.first << ", " << *range.second << ")" << endl;

    // Inplace Merge (merge)
    merge(myList.begin(), myList.end(), secondList.begin(), secondList.end(), myList.begin());
    cout << "Inplace Merge - Merged myList and secondList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Lower Bound (lower_bound)
    auto insertPos = lower_bound(myList.begin(), myList.end(), 5);
    cout << "Lower Bound - Insert position for 5: " << distance(myList.begin(), insertPos) << endl;

    // Merge (merge)
    list<int> mergedList;
    merge(myList.begin(), myList.end(), thirdList.begin(), thirdList.end(), back_inserter(mergedList));
    cout << "Merge - Merged myList and thirdList into a new list: ";
    for (const auto &element : mergedList) {
        cout << element << " ";
    }
    cout << endl;

    // Partition (partition)
    partition(myList.begin(), myList.end(), [](int x) { return x % 2 == 0; });
    cout << "Partition - Even numbers moved to the front: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Sort (sort)
    sort(myList.begin(), myList.end());
    cout << "Sort - Sorted myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Upper Bound (upper_bound)
    auto upperPos = upper_bound(myList.begin(), myList.end(), 5);
    cout << "Upper Bound - Insert position after last occurrence of 5: " << distance(myList.begin(), upperPos) << endl;

    // Max (max)
    int larger = max(10, 5);
    cout << "Max - Larger of 10 and 5: " << larger << endl;

    // Max Element (max_element)
    auto maxElem = max_element(myList.begin(), myList.end());
    cout << "Max Element - Maximum element in myList: " << *maxElem << endl;

    // Min (min)
    int smaller = min(10, 5);
    cout << "Min - Smaller of 10 and 5: " << smaller << endl;

    // Min Element (min_element)
    auto minElem = min_element(myList.begin(), myList.end());
    cout << "Min Element - Minimum element in myList: " << *minElem << endl;

    // Accumulate (accumulate)
    int sum = accumulate(myList.begin(), myList.end(), 0);
    cout << "Accumulate - Sum of elements in myList: " << sum << endl;

    // Reverse (reverse)
    reverse(myList.begin(), myList.end());
    cout << "Reverse - Reversed myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Unique (unique)
    myList.unique();
    cout << "Unique - Consecutive duplicates removed from myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Remove (remove)
    myList.remove(5);
    cout << "Remove - Elements equal to 5 removed from myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Remove If (remove_if)
    myList.remove_if([](int x) { return x % 2 == 0; });
    cout << "Remove If - Even elements removed from myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    // Splice (splice)
    auto splicePoint = myList.begin();  // Assume a valid iterator position
    myList.splice(splicePoint, secondList);
    cout << "Splice - Elements from anotherList spliced into myList: ";
    for (const auto &element : myList) {
        cout << element << " ";
    }
    cout << endl;

    return 0;
}

OUTPUT:

Binary Search - Element 5 exists: Yes
Equal Range - Range of elements matching 5: [5, 6)
Inplace Merge - Merged myList and secondList: 1 2 3 4 5 5 6 7 8 9 
Lower Bound - Insert position for 5: 4
Merge - Merged myList and thirdList into a new list: 1 2 3 4 5 5 6 10 11 12 
Partition - Even numbers moved to the front: 2 4 6 1 3 5 5 10 11 12 
Sort - Sorted myList: 1 2 3 4 5 5 6 10 11 12 
Upper Bound - Insert position after last occurrence of 5: 6
Max - Larger of 10 and 5: 10
Max Element - Maximum element in myList: 12
Min - Smaller of 10 and 5: 5
Min Element - Minimum element in myList: 1
Accumulate - Sum of elements in myList: 55
Reverse - Reversed myList: 12 11 10 6 5 5 4 3 2 1 
Unique - Consecutive duplicates removed from myList: 12 11 10 6 5 4 3 2 1 
Remove - Elements equal to 5 removed from myList: 12 11 10 6 4 3 2 1 
Remove If - Even elements removed from myList: 11 3 1 
Splice - Elements from anotherList spliced into myList: 7 8 9 11 3 1

N.B: ALGORITHMS NOT DIRECTLY APPLICABLE TO LIST:

Make Heap:

Works: Rearranges elements in a range to form a binary heap (max-heap by default).

Syntax: make_heap(begin, end)

Example: make_heap(myList.begin(), myList.end())

Sort Heap:

Works: Sorts the elements in a range that represents a binary heap.

Syntax: sort_heap(begin, end)

Example: sort_heap(myList.begin(), myList.end())

Stable Sort:

Works: Sorts elements in a range while preserving the relative order of equal elements.

Syntax: stable_sort(begin, end)

Example: stable_sort(myList.begin(), myList.end())

CONGRATULATION NOW YOU ARE THE MASTER OF LIST CONTAINER

11
Subscribe to my newsletter

Read articles from AL NAFIS FUAD SHUVO directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

AL NAFIS FUAD SHUVO
AL NAFIS FUAD SHUVO