📜  实现单个链表的迭代器模式

📅  最后修改于: 2021-09-10 02:43:56             🧑  作者: Mango

STL 是 C++ 的支柱之一。它让生活变得更轻松,尤其是当您专注于解决问题并且不想花时间实施已经可用的东西时,这保证了稳健的解决方案。软件工程的关键方面之一是避免重新发明轮子。可重用性始终是首选。

虽然依赖库函数直接影响我们的效率,但如果没有正确理解它是如何工作的,有时就会失去我们一直在谈论的工程效率的意义。错误选择的数据结构可能会在未来某个时候再次困扰我们。解决方法很简单。使用库方法,但要知道它是如何处理幕后操作的。

说够了!今天我们将看看如何实现我们自己的单个链表迭代器模式。所以,这是链表的 STL 实现的样子:

C++
#include 
using namespace std;
 
int main()
{
    // creating  a list
    vector 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::iterator it = list.begin();
                                it != list.end(); ++it)
        cout << *it << " ";
 
    return 0;
}


Java
import java.util.*;
class GFG
{
 
    public static void main(String[] args)
    {
       
        // creating  a list
        ArrayList 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 it = list.iterator();
        while (it.hasNext())
        {
            System.out.print(it.next() + " ");
        }
    }
}
 
// This code is contributed by pratham76


Python3
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


C#
using System;
using System.Collections.Generic;
 
public class GFG {
 
    public static void Main(String[] args) {
 
        // creating a list
        List list = new List();
 
        // 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


Javascript


C++
// C++ program to implement Custom Linked List and
// iterator pattern.
#include 
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 here
template 
class LinkedList
{
    // Forward declaration
    class Node;
 
public:
    LinkedList() 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 
/*static*/ typename LinkedList::Node* LinkedList::m_spRoot = nullptr;
 
template 
void LinkedList::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 
void LinkedList::Traverse()
{
    Node* pCrawler = GetRootNode();
 
    while (pCrawler)
    {
        cout << pCrawler->data << " ";
        pCrawler = pCrawler->pNext;
    }
 
    cout << endl;
}
 
//Driver program
int main()
{
    LinkedList 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::Iterator iterator = list.begin();
            iterator != list.end(); iterator++)
    {
        cout << *iterator << " ";
    }
 
    cout << endl;
 
    return 0;
}


输出

1 2 3

cincout 的优点之一是它们不需要格式说明符来处理数据类型。这与模板的结合使代码更加清晰和可读。尽管我更喜欢 C++ 中的命名方法以大写字母开头,但此实现遵循 STL 规则来模拟方法调用的确切集合,即 push_back、begin、end。

这是我们自己实现的 LinkedList 及其迭代器模式:

C++

// C++ program to implement Custom Linked List and
// iterator pattern.
#include 
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 here
template 
class LinkedList
{
    // Forward declaration
    class Node;
 
public:
    LinkedList() 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 
/*static*/ typename LinkedList::Node* LinkedList::m_spRoot = nullptr;
 
template 
void LinkedList::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 
void LinkedList::Traverse()
{
    Node* pCrawler = GetRootNode();
 
    while (pCrawler)
    {
        cout << pCrawler->data << " ";
        pCrawler = pCrawler->pNext;
    }
 
    cout << endl;
}
 
//Driver program
int main()
{
    LinkedList 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::Iterator iterator = list.begin();
            iterator != list.end(); iterator++)
    {
        cout << *iterator << " ";
    }
 
    cout << endl;
 
    return 0;
}

输出:

Traversing LinkedList through method
1 2 3 
Traversing LinkedList through Iterator
1 2 3

锻炼:
当我们有一个数据时,上述实现效果很好。扩展此代码以处理包装在类中的一组数据。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程