在尝试使用类似内部STL的迭代器创建双向链表时,我编写了以下代码。我现在只提供带有非相关部分的头文件。
我的问题是......
STL以某种方式使用迭代器 - 具体来说,您从.begin()迭代器中导航到STL容器,但不包括.end()迭代器。要做到这一点,.end()迭代器必须是容器末尾的一个。考虑到我的开始,我将如何实现这种语义(这是主要问题)?
接口中是否有任何缺失(关于迭代器类和应该存在的东西)?
以下是代码:
template <typename T>
class Node
{
T data;
Node<T>* next;
Node<T>* prev;
};
template <typename T>
class LinkedList
{
public:
class Iterator
{
public:
Iterator() {}
explicit Iterator(const Node<T>& init) { current = init; }
//Dereference operator - return the current node's data.
inline T& operator*() { return current->data; }
//Prefix returns by reference.
inline Iterator& operator++() { current = current->next; return *this; }
inline Iterator& operator--() { current = current->prev; return *this; }
//Postfix returns non-reference and has int parameter to differentiate function signature.
inline Iterator operator++(int) { Iterator res = *this; current = current->next; return res; }
inline Iterator operator--(int) { Iterator res = *this; current = current->prev; return res; }
private:
Node<T>* current;
};
Iterator begin() { return Iterator(m_start); }
Iterator end() { return Iterator(m_end); }
private:
Node<T>* m_start;
Node<T>* m_end;
};
我知道我可能会或者可能没有使用++ / - 运算符的问题,但这并不会让我感到特别烦恼,因为当我有足够的代码对此进行一些测试时,我会解决这些问题。 。如果您愿意,请随意提示:)
答案 0 :(得分:2)
end()
返回的迭代器必须是可递减的,否则您无法反向迭代列表。
你可以通过让Iterator存储两个指针来实现这一点:当前节点(结束时为NULL)和前一个节点(允许你找到包含数据的最后一个节点,即使是current == NULL
。 / p>
class Iterator
{
public:
Iterator() {}
explicit Iterator(Node<T>* curr, Node<T>* prev):
current(curr), previous(prev) {}
//Dereference operator - return the current node's data.
inline T& operator*() { return current->data; }
//Prefix returns by reference.
inline Iterator& operator++()
{
previous = current;
current = current->next;
return *this;
}
inline Iterator& operator--()
{
current = previous;
previous = current->previous;
return *this;
}
//Postfix should be implemented in terms of prefix operators
inline Iterator operator++(int) { Iterator res = *this; ++*this; return res; }
inline Iterator operator--(int) { Iterator res = *this; --*this; return res; }
private:
Node<T>* current;
Node<T>* previous;
};
Iterator begin() { return Iterator(m_start, 0); }
Iterator end() { return Iterator(0, m_end); }
或者,您可以让列表包含指定列表“一个接一个结尾”的标记节点。但是,此节点不应具有数据成员。这可以通过将Node类拆分为非模板库来实现,只需指向下一个节点和上一个节点。
例如,看起来GCC的列表实现存储了一个指向sentinel的指针,因此它的next
指向列表中的第一个项目,而它的prev
指向列表中的最后一个项目(如果列表为空,则两者都指向自身。)
您缺少operator->
,operator==
和operator!=
,分类typedef可以从std::iterator继承,const_iterator实现(迭代器应该可以隐式转换)到const_iterator)。
答案 1 :(得分:1)
第一个节点的上级指针为NULL,最后一个节点的下一个指针也是如此。一个接一个的current
指针将为NULL。
operator->
答案 2 :(得分:1)
for (iterator it = list.begin(); it != list.end(); it++)
的内容,因此您也需要定义比较运算符。