Tag: list

  • Data Structures and Corresponding STL

    Data Structures and Corresponding STL

    The C++ Standard Template Library (STL) is a collection of powerful and flexible generic classes and functions designed to manage common data structures and algorithms. It provides efficient, reusable implementations of many data structures, which makes it easier to write high-performance code. Below is a detailed overview of common data structures and their corresponding STL components.

    1. Arrays

    Description:

    • Fixed-size, sequential containers for elements of the same type.
    • Used for storing data in contiguous memory.

    STL Component:

    • std::array (C++11)
    • std::vector

    Operations:

    • Random access: O(1)O(1)
    • Insertion/Deletion: O(n)O(n) for shifting elements.

    Example:

    #include <iostream>
    #include <array>
    
    int main() {
        std::array<int, 5> arr = {1, 2, 3, 4, 5};
        for (const auto& val : arr) {
            std::cout << val << " ";
        }
        return 0;
    }

    2. Linked List

    Description:

    • Sequential data structure with nodes that hold data and a pointer to the next node.

    STL Component:

    • std::list (Doubly Linked List)
    • std::forward_list (Singly Linked List)

    Operations:

    • Insertion/Deletion at any position: O(1)O(1)
    • Traversal: O(n)O(n)

    Example:

    #include <iostream>
    #include <list>
    
    int main() {
        std::list<int> lst = {10, 20, 30};
        lst.push_back(40);   // Add to the end
        lst.push_front(5);   // Add to the beginning
    
        for (const auto& val : lst) {
            std::cout << val << " ";
        }
        return 0;
    }

    3. Stack

    Description:

    • Last-In-First-Out (LIFO) data structure.

    STL Component:

    • std::stack (adaptor over std::deque)

    Operations:

    • Push: O(1)O(1)
    • Pop: O(1)O(1)
    • Top (peek): O(1)O(1)

    Example:

    #include <iostream>
    #include <stack>
    
    int main() {
        std::stack<int> st;
        st.push(10);
        st.push(20);
        st.push(30);
    
        while (!st.empty()) {
            std::cout << st.top() << " ";
            st.pop();
        }
        return 0;
    }

    4. Queue

    Description:

    • First-In-First-Out (FIFO) data structure.

    STL Component:

    • std::queue (adaptor over std::deque)
    • std::deque (Double-Ended Queue)

    Operations:

    • Enqueue: O(1)O(1)
    • Dequeue: O(1)O(1)
    • Front/Back: O(1)O(1)

    Example:

    #include <iostream>
    #include <queue>
    
    int main() {
        std::queue<int> q;
        q.push(10);
        q.push(20);
        q.push(30);
    
        while (!q.empty()) {
            std::cout << q.front() << " ";
            q.pop();
        }
        return 0;
    }

    5. Priority Queue

    Description:

    • Specialized queue where elements are dequeued in priority order (not FIFO).
    • Default is a max-heap.

    STL Component:

    • std::priority_queue

    Operations:

    • Push: O(log⁡n)O(\log n)
    • Pop: O(log⁡n)O(\log n)
    • Top: O(1)O(1)

    Example:

    #include <iostream>
    #include <queue>
    
    int main() {
        std::priority_queue<int> pq;
        pq.push(10);
        pq.push(20);
        pq.push(15);
    
        while (!pq.empty()) {
            std::cout << pq.top() << " ";
            pq.pop();
        }
        return 0;
    }

    Output:

    20 15 10

    6. Set

    Description:

    • Ordered container for unique elements.

    STL Component:

    • std::set
    • std::unordered_set (Hash-based)

    Operations:

    • Insertion/Deletion/Find: O(log⁡n)O(\log n) for std::set, O(1)O(1) for std::unordered_set.

    Example:

    #include <iostream>
    #include <set>
    
    int main() {
        std::set<int> s;
        s.insert(10);
        s.insert(20);
        s.insert(20); // Ignored as duplicate
    
        for (const auto& val : s) {
            std::cout << val << " ";
        }
        return 0;
    }

    7. Map

    Description:

    • Key-value pairs with unique keys.

    STL Component:

    • std::map (Ordered)
    • std::unordered_map (Hash-based)
    • std::multimap (Allows duplicate keys)

    Operations:

    • Insertion/Deletion/Access: O(log⁡n)O(\log n) for std::map, O(1)O(1) for std::unordered_map.

    Example:

    #include <iostream>
    #include <map>
    
    int main() {
        std::map<int, std::string> m;
        m[1] = "One";
        m[2] = "Two";
    
        for (const auto& pair : m) {
            std::cout << pair.first << ": " << pair.second << std::endl;
        }
        return 0;
    }

    8. Graph

    Description:

    • A network of nodes (vertices) connected by edges.
    • Can be represented using adjacency lists or matrices.

    STL Component:

    • std::vector<std::vector<int>> (Adjacency List)
    • std::set or std::map for weighted edges.

    Example: Adjacency List

    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<std::vector<int>> graph(5);
    
        // Add edges
        graph[0].push_back(1);
        graph[1].push_back(2);
        graph[2].push_back(3);
    
        // Print adjacency list
        for (int i = 0; i < graph.size(); i++) {
            std::cout << i << ": ";
            for (int neighbor : graph[i]) {
                std::cout << neighbor << " ";
            }
            std::cout << std::endl;
        }
        return 0;
    }

    9. Hash Tables

    Description:

    • Containers for key-value pairs with hash-based lookups.

    STL Component:

    • std::unordered_map
    • std::unordered_set

    Operations:

    • Insertion/Deletion/Access: O(1)O(1)

    Example:

    #include <iostream>
    #include <unordered_map>
    
    int main() {
        std::unordered_map<std::string, int> umap;
        umap["Apple"] = 10;
        umap["Banana"] = 20;
    
        for (const auto& pair : umap) {
            std::cout << pair.first << ": " << pair.second << std::endl;
        }
        return 0;
    }

    Summary of Common Data Structures and STL

    Data StructureSTL ComponentInsertionLookupOrder
    Arraystd::array, std::vectorO(1)O(1) O(1)O(1) Sequential
    Linked Liststd::list, std::forward_listO(1)O(1)O(n)O(n)Sequential
    Stackstd::stackO(1)O(1)O(1)O(1)LIFO
    Queuestd::queue, std::dequeO(1)O(1)O(1)O(1)FIFO
    Priority Queuestd::priority_queueO(log⁡n)O(\log n)O(1)O(1)By Priority
    Setstd::set, std::unordered_setO(log⁡n)O(\log n)O(log⁡n)O(\log n)Sorted
    Mapstd::map, std::unordered_mapO(log⁡n)O(\log n)O(log⁡n)O(\log n)By Key

  • C++ Standard Template Library (STL)

    The C++ Standard Template Library (STL) is a powerful collection of generic classes and functions that provide commonly used data structures and algorithms. It allows developers to work with collections of data (containers) and perform common tasks such as searching, sorting, and manipulation efficiently.

    Key Components of the STL

    The STL is primarily divided into four main components:

    1. Containers

    Containers are data structures used to store collections of elements. The STL provides several container types, each optimized for specific use cases:

    Sequence Containers:

    • Store data in a linear fashion.
    • Examples:
      • std::vector: Dynamic array.
      • std::deque: Double-ended queue.
      • std::list: Doubly linked list.
      • std::array: Fixed-size array.

    Associative Containers:

    • Store data in sorted order, typically as key-value pairs.
    • Examples:
      • std::set: Collection of unique keys.
      • std::map: Key-value pairs with unique keys.
      • std::multiset: Allows duplicate keys.
      • std::multimap: Allows duplicate key-value pairs.

    Unordered Containers:

    • Use hashing for faster access but do not guarantee order.
    • Examples:
      • std::unordered_set
      • std::unordered_map
      • std::unordered_multiset
      • std::unordered_multimap

    Container Adapters:

    • Provide a modified interface for existing containers.
    • Examples:
      • std::stack: LIFO (Last In First Out).
      • std::queue: FIFO (First In First Out).
      • std::priority_queue: Queue with elements sorted by priority.

    2. Iterators

    Iterators provide a way to traverse containers. They act like pointers and can access elements of a container sequentially.

    Types of Iterators:

    • Input Iterator: For reading data (e.g., istream_iterator).
    • Output Iterator: For writing data (e.g., ostream_iterator).
    • Forward Iterator: Single-pass traversal (e.g., std::forward_list).
    • Bidirectional Iterator: Forward and backward traversal (e.g., std::list).
    • Random Access Iterator: Access any element in constant time (e.g., std::vector).

    3. Algorithms

    Algorithms in the STL are generic functions that operate on containers through iterators. They implement common tasks like searching, sorting, modifying, and more.

    Examples:

    • Searching:
      • std::find: Find an element.
      • std::binary_search: Perform binary search (requires sorted range).
    • Sorting:
      • std::sort: Sort elements in ascending order.
      • std::stable_sort: Maintains relative order of equivalent elements.
    • Modifying:
      • std::copy: Copy elements.
      • std::transform: Apply a function to elements.
      • std::replace: Replace specific elements.
    • Others:
      • std::for_each: Apply a function to each element.
      • std::accumulate: Accumulate the result of a function over a range.

    4. Functors and Lambdas

    Functors (Function Objects) and lambdas provide callable objects that can be passed to STL algorithms for custom operations.

    Functors:

    • Objects that behave like functions by overloading the operator().
    struct Square {
        int operator()(int x) const { return x * x; }
    };

    Lambdas:

    • Anonymous functions that can capture variables and provide custom logic.
    std::for_each(vec.begin(), vec.end(), [](int x) {
        std::cout << x << " "; 
    });

    Advantages of STL

    • Reusability: Reduces the need to reinvent common data structures and algorithms.
    • Efficiency: Optimized implementations with consistent time complexities.
    • Portability: Part of the C++ standard, making it portable across platforms.
    • Generality: Provides generic, type-safe solutions via templates.

    Example: Using STL for Sorting and Searching

    #include <iostream>
    #include <vector>
    #include <algorithm> // For sort and binary_search
    
    int main() {
        std::vector<int> numbers = {10, 2, 33, 45, 23};
    
        // Sort the vector
        std::sort(numbers.begin(), numbers.end());
    
        // Display sorted elements
        for (const auto& num : numbers)
            std::cout << num << " ";
        std::cout << std::endl;
    
        // Perform a binary search
        int target = 33;
        if (std::binary_search(numbers.begin(), numbers.end(), target)) {
            std::cout << target << " found." << std::endl;
        } else {
            std::cout << target << " not found." << std::endl;
        }
    
        return 0;
    }

    Best Practices

    1. Choose the Right Container: Use containers suited to your data and access patterns.
    2. Leverage Algorithms: Avoid writing custom loops when STL algorithms can suffice.
    3. Use Range-Based Loops: For cleaner and safer iteration over containers.
    4. Optimize with Move Semantics: Use std::move for efficient data transfers.
    5. Avoid Manual Memory Management: Use containers like std::vector and std::shared_ptr to manage resources automatically.