Home C++ C++ Standard Template Library (STL) list tutorial

C++ Standard Template Library (STL) list tutorial

The list container in the C++ Standard Template Library (STL) is a doubly linked list.

Unlike arrays or vectors, list allows fast insertion and deletion at both ends, as well as in the middle, without reallocating or shifting elements.

It’s ideal for situations where frequent insertions or deletions are needed but random access is not a priority.

Key Features of list

  1. Doubly Linked List: Supports forward and backward traversal.
  2. Efficient Insertions and Deletions: Operations at the front, back, or middle are efficient.
  3. Bidirectional Traversal: Supports reverse iterators.

Basic Syntax

#include <list>
using namespace std;

list<int> lst;

Let’s explore common operations and examples to understand how list works.

1. Initializing a list

A list can be initialized with default values, a specified size, or with an initializer list.

#include <iostream>
#include <list>
using namespace std;

int main() {
    // Empty list
    list<int> lst1;

    // Initialize with values
    list<int> lst2 = {10, 20, 30, 40, 50};

    // Display elements
    cout << "Elements in lst2: ";
    for (int val : lst2) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements in lst2: 10 20 30 40 50 

2. Adding Elements

list supports push_front and push_back for adding elements to the front and back, respectively. emplace_front and emplace_back can also be used for in-place construction.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {20, 30, 40};

    // Add elements at the front and back
    lst.push_front(10);
    lst.push_back(50);

    cout << "Elements after push_front and push_back: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after push_front and push_back: 10 20 30 40 50 

3. Inserting Elements at Specific Positions

The insert function allows insertion at specific positions within the list.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 40};

    // Insert 30 at the second position
    auto it = lst.begin();
    advance(it, 2);
    lst.insert(it, 30);

    cout << "Elements after insertion: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after insertion: 10 20 30 40 

4. Removing Elements

You can remove elements using pop_front and pop_back. The remove function removes all occurrences of a specific value, while erase removes elements at a specific position.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30, 40, 50, 30};

    // Remove first and last elements
    lst.pop_front();
    lst.pop_back();

    // Remove all occurrences of 30
    lst.remove(30);

    cout << "Elements after removals: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after removals: 20 40 

5. Accessing Elements

list does not support random access (no [] operator or at function), so you must use iterators to access elements.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30, 40, 50};

    cout << "Elements: ";
    for (auto it = lst.begin(); it != lst.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements: 10 20 30 40 50 

6. Resizing a list

The resize function changes the number of elements in the list. If the new size is greater, new elements are added with a specified default value; if smaller, extra elements are removed.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30};

    // Resize to larger size with default value 0
    lst.resize(5, 0);

    cout << "Elements after resizing to 5: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    // Resize to smaller size
    lst.resize(2);
    cout << "Elements after resizing to 2: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after resizing to 5: 10 20 30 0 0 
Elements after resizing to 2: 10 20 

7. Sorting a list

The sort function sorts elements in ascending order.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {50, 10, 40, 30, 20};

    // Sorting the list
    lst.sort();

    cout << "Elements after sorting: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after sorting: 10 20 30 40 50 

8. Reversing a list

The reverse function reverses the order of elements in the list.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst = {10, 20, 30, 40, 50};

    // Reversing the list
    lst.reverse();

    cout << "Elements after reversing: ";
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements after reversing: 50 40 30 20 10 

9. Merging Two lists

The merge function merges two sorted lists into one sorted list. Both lists must be sorted beforehand.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst1 = {10, 30, 50};
    list<int> lst2 = {20, 40, 60};

    // Merging two sorted lists
    lst1.merge(lst2);

    cout << "Merged list: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

Merged list: 10 20 30 40 50 60 

10. Splicing Elements from One List to Another

The splice function transfers elements from one list to another at a specified position.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst1 = {10, 20, 30};
    list<int> lst2 = {40, 50, 60};

    // Splicing lst2 into lst1 after the first element
    auto it = lst1.begin();
    ++it;
    lst1.splice(it, lst2);

    cout << "List 1 after splicing: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    cout << "List 2 after splicing (should be empty): ";
    for (int val : lst2) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Output:

List 1 after splicing: 10 40 50 60 20 30 
List 2 after splicing (should be empty): 

Summary Table of list Operations

Operation Code Example Description
Initialize list<int> lst = {10, 20, 30}; Creates a list with initial values
Add at front lst.push_front(5); Adds an element to the front
Add at back lst.push_back(50); Adds an element to the back
Insert at position lst.insert(it, 25); Inserts element at a specified position
Remove from front lst.pop_front(); Removes the first element
Remove from back lst.pop_back(); Removes the last element
Remove specific value lst.remove(30); Removes all occurrences of a specified value
Clear lst.clear(); Removes all elements
Resize lst.resize(5, 100); Resizes list, fills new slots with default value
Sort lst.sort(); Sorts elements in ascending order
Reverse lst.reverse(); Reverses the order of elements
Merge lst1.merge(lst2); Merges two sorted lists
Splice lst1.splice(it, lst2); Transfers elements from lst2 into lst1

Complete Example

This example demonstrates initializing a list, adding and removing elements, sorting, reversing, merging, and splicing.

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst1 = {10, 20, 30};
    list<int> lst2 = {15, 25, 35};

    // Add elements
    lst1.push_front(5);
    lst1.push_back(40);

    cout << "List 1 after adding elements: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    // Sort and reverse
    lst1.sort();
    lst1.reverse();

    cout << "List 1 after sorting and reversing: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    // Merge with another sorted list
    lst1.sort();
    lst2.sort();
    lst1.merge(lst2);

    cout << "List 1 after merging with List 2: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    // Splice elements
    list<int> lst3 = {50, 60};
    auto it = lst1.begin();
    advance(it, 3);
    lst1.splice(it, lst3);

    cout << "List 1 after splicing with List 3: ";
    for (int val : lst1) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

Sample Output:

List 1 after adding elements: 5 10 20 30 40 
List 1 after sorting and reversing: 40 30 20 10 5 
List 1 after merging with List 2: 5 10 15 20 25 30 35 40 
List 1 after splicing with List 3: 5 10 15 50 60 20 25 30 35 40 

Key Takeaways

  • list is a doubly linked list, suitable for efficient insertions and deletions.
  • It allows bidirectional traversal with iterators, supporting operations like insertion, deletion, sorting, reversing, merging, and splicing.
  • list is ideal when random access isn’t needed, and you need frequent modifications at both ends or in the middle.

You may also like