Implementing Iterator pattern of a single Linked List - GeeksforGeeks

19 May, 2021
STL is one of the pillars of C++. It makes life a lot easier, especially when your focus is on problem-solving and you don’t want to spend time implementing something that is already available which guarantees a robust solution. One of the key aspects of Software Engineering is to avoid reinventing the wheel. Reusability is always preferred.
While relying on library functions directly impacts our efficiency, without having a proper understanding of how it works sometimes loses the meaning of the engineering efficiency we keep on talking about. A wrongly chosen data structure may come back sometime in the future to haunt us. The solution is simple. Use library methods, but know how does it handle operations under the hood.
Enough said! Today we will look at how we can implement our own Iterator pattern of a single Linked List. So, here is how an STL implementation of Linked List looks like: 
C++
Java
Python3
C#
Javascript
#include <bits/stdc++.h>using namespace std; int main(){    // creating  a list    vector<int> list;     // elements to be added at the end.    // in the above created list.    list.push_back(1);    list.push_back(2);    list.push_back(3);     // elements of list are retrieved through iterator.    for (vector<int>::iterator it = list.begin();                                it != list.end(); ++it)        cout << *it << " ";     return 0;}
import java.util.*;class GFG{     public static void main(String[] args)    {               // creating  a list        ArrayList<Integer> list = new ArrayList<>();         // elements to be added at the end.        // in the above created list.        list.add(1);        list.add(2);        list.add(3);         // elements of list are retrieved through iterator.        Iterator<Integer> it = list.iterator();        while (it.hasNext())        {            System.out.print(it.next() + " ");        }    }} // This code is contributed by pratham76
if __name__=='__main__':         # Creating  a list    list = []      # Elements to be added at the end.    # in the above created list.    list.append(1)    list.append(2)    list.append(3)         # Elements of list are retrieved    # through iterator.    for it in list:        print(it, end = ' ')     # This code is contributed by rutvik_56
using System;using System.Collections.Generic; public class GFG {     public static void Main(String[] args) {         // creating a list        List<int> list = new List<int>();         // elements to be added at the end.        // in the above created list.        list.Add(1);        list.Add(2);        list.Add(3);         // elements of list are retrieved through iterator.                 foreach (int it in list) {            Console.Write(it + " ");        }    }}  // This code contributed by umadevi9616
     <script>         // creating a list        var list =  [];         // elements to be added at the end.        // in the above created list.        list.push(1);        list.push(2);        list.push(3);         // elements of list are retrieved through iterator.             for (var i = 0; i<list.length;i++) {            document.write(list[i] + " ");        } // This code contributed by umadevi9616 </script>
Output
1 2 3
One of the beauties of cin and cout is that they don’t demand format specifiers to work with the type of data. This combined with templates makes the code much cleaner and readable. Although I prefer the naming method in C++ to start with caps, this implementation follows STL rules to mimic the exact set of method calls, viz push_back, begin, end.
Here is our own implementation of LinkedList and its Iterator pattern:  
C++
// C++ program to implement Custom Linked List and// iterator pattern.#include <bits/stdc++.h>using namespace std; // Custom class to handle Linked List operations// Operations like push_back, push_front, pop_back,// pop_front, erase, size can be added heretemplate <typename T>class LinkedList{    // Forward declaration    class Node; public:    LinkedList<T>() noexcept    {        // caution: static members can't be        // initialized by initializer list        m_spRoot = nullptr;    }     // Forward declaration must be done    // in the same access scope    class Iterator;     // Root of LinkedList wrapped in Iterator type    Iterator begin()    {        return Iterator(m_spRoot);    }     // End of LInkedList wrapped in Iterator type    Iterator end()    {        return Iterator(nullptr);    }     // Adds data to the end of list    void push_back(T data);     void Traverse();     // Iterator class can be used to    // sequentially access nodes of linked list    class Iterator    {    public:    Iterator() noexcept :        m_pCurrentNode (m_spRoot) { }     Iterator(const Node* pNode) noexcept :        m_pCurrentNode (pNode) { }         Iterator& operator=(Node* pNode)        {            this->m_pCurrentNode = pNode;            return *this;        }         // Prefix ++ overload        Iterator& operator++()        {            if (m_pCurrentNode)                m_pCurrentNode = m_pCurrentNode->pNext;            return *this;        }         // Postfix ++ overload        Iterator operator++(int)        {            Iterator iterator = *this;            ++*this;            return iterator;        }         bool operator!=(const Iterator& iterator)        {            return m_pCurrentNode != iterator.m_pCurrentNode;        }         int operator*()        {            return m_pCurrentNode->data;        }     private:        const Node* m_pCurrentNode;    }; private:     class Node    {        T data;        Node* pNext;         // LinkedList class methods need        // to access Node information        friend class LinkedList;    };     // Create a new Node    Node* GetNode(T data)    {        Node* pNewNode = new Node;        pNewNode->data = data;        pNewNode->pNext = nullptr;         return pNewNode;    }     // Return by reference so that it can be used in    // left hand side of the assignment expression    Node*& GetRootNode()    {        return m_spRoot;    }     static Node* m_spRoot;}; template <typename T>/*static*/ typename LinkedList<T>::Node* LinkedList<T>::m_spRoot = nullptr; template <typename T>void LinkedList<T>::push_back(T data){    Node* pTemp = GetNode(data);    if (!GetRootNode())    {        GetRootNode() = pTemp;    }    else    {        Node* pCrawler = GetRootNode();        while (pCrawler->pNext)        {            pCrawler = pCrawler->pNext;        }         pCrawler->pNext = pTemp;    }} template <typename T>void LinkedList<T>::Traverse(){    Node* pCrawler = GetRootNode();     while (pCrawler)    {        cout << pCrawler->data << " ";        pCrawler = pCrawler->pNext;    }     cout << endl;} //Driver programint main(){    LinkedList<int> list;     // Add few items to the end of LinkedList    list.push_back(1);    list.push_back(2);    list.push_back(3);     cout << "Traversing LinkedList through method" << endl;    list.Traverse();     cout << "Traversing LinkedList through Iterator" << endl;    for ( LinkedList<int>::Iterator iterator = list.begin();            iterator != list.end(); iterator++)    {        cout << *iterator << " ";    }     cout << endl;     return 0;}
Output: 
Traversing LinkedList through method
1 2 3 
Traversing LinkedList through Iterator
1 2 3
Exercise: The above implementation works well when we have one data. Extend this code to work for a set of data wrapped in a class.
This article is contributed by Aashish Barnwal. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
rutvik_56
pratham76
umadevi9616
STL
C++
Design Pattern
Linked List
Linked List
STL
CPP
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Virtual Function in C++
Operator Overloading in C++
Templates in C++ with Examples
vector erase() and clear() in C++
Socket Programming in C/C++
SDE SHEET - A Complete Guide for SDE Preparation
Design Patterns | Set 1 (Introduction)
Singleton Design Pattern | Implementation
Unified Modeling Language (UML) | Sequence Diagrams
Factory method design pattern in Java