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
cin和cout 的优点之一是它们不需要格式说明符来处理数据类型。这与模板的结合使代码更加清晰和可读。尽管我更喜欢 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 现场工作专业课程和学生竞争性编程现场课程。