LIST in C++ STL

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

Did you find this article valuable?

Support AL NAFIS FUAD SHUVO's blog by becoming a sponsor. Any amount is appreciated!