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

📅  最后修改于: 2021-05-30 12:47:02             🧑  作者: Mango

STL是C++的支柱之一。它使工作变得更加轻松,尤其是当您专注于解决问题并且不想花时间去实施已经可以保证可靠解决方案的事情时,尤其如此。软件工程的关键方面之一是避免重新发明轮子。可重用性始终是首选。

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

说够了!今天,我们将研究如何实现单个链表的自己的Iterator模式。因此,这是链接列表的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++
// 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及其Iterator模式的实现:

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

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

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”