链表迭代器实现C++; 我在C++中创建了一个链表,并想实现它的迭代器,这样我就可以做范围循环:(const int和i:list)< /Cord> >代码> LINKEDYLISTROL列表;
我的想法是创建链表迭代器实现C++; 我在C++中创建了一个链表,并想实现它的迭代器,这样我就可以做范围循环:(const int和i:list)< /Cord> >代码> LINKEDYLISTROL列表;,c++,data-structures,iterator,C++,Data Structures,Iterator,我的想法是创建迭代器,作为链表类的一部分,如下所示: struct Iterator { T& operator*() const { return current->value; } bool operator!=(const Iterator& rhs) { return (*_current != rhs._current); } Iterator& operator++() { current = curren
迭代器
,作为链表
类的一部分,如下所示:
struct Iterator
{
T& operator*() const { return current->value; }
bool operator!=(const Iterator& rhs) { return (*_current != rhs._current); }
Iterator& operator++()
{
current = current->next;
return *this;
}
};
到目前为止,我得到的是:
template <typename T>
class Linked_List
{
public:
struct Iterator;
struct Node;
public:
Linked_List();
~Linked_List() noexcept(false);
Linked_List(const Linked_List&) = delete;
Linked_List(Linked_List&&) = delete;
Linked_List& operator=(const Linked_List&) = delete;
Linked_List& operator=(Linked_List&&) = delete;
void push_back(T);
void push_front(T);
void pop_back();
void pop_front();
bool empty() const;
T back() const;
T front() const;
//void swap(T, T);
//void insert(Iterator, T);
//void erase(Iterator);
//Iterator begin() const;
//Iterator end() const;
private:
Node* head;
Node* tail;
};
template<typename T>
struct Linked_List<T>::Node
{
Node() : prev(nullptr), next(nullptr) {}
Node(T t) : value(t), prev(nullptr), next(nullptr) {}
Node* prev;
Node* next;
T value;
};
如何实现迭代器链表::begin()const代码>和end()
现在
我想象一个虚构的用户创建一个迭代器对象,如下所示:
链表::迭代器代码>
一个想法是让一个没有参数的公共构造函数和一个私有构造函数将一个节点作为参数,当前的将被设置为,并让链接列表类作为朋友。一些注意事项
有两个选项可用于声明节点
和迭代器
。在列表类内部为list::Node
或外部为Node
。这在某种程度上是一个品味问题。然而,从工程的角度来看,嵌套类的符号名更长,因此您的debuginfo更大。另外,当嵌套类也是模板时,在必要时(因为这需要首先完全专门化封闭模板),很难专门化它们,但这里的情况并非如此
当一个列表节点用作列表的头和尾时,它会产生更优雅的代码。空列表是其next
和prev
指向自身的节点push_front
附加到列表。下一步
指向第一个节点或其自身push_back
将一个节点附加到list.prev
中,该节点指向最后一个节点或其自身。插入/删除节点时,无需对第一个和最后一个节点进行特殊处理。例如:
struct Node {
Node *next_, *prev_;
Node()
: next_(this), prev_(this)
{}
~Node() {
unlink();
}
void push_back(Node* n) {
n->next_ = this;
n->prev_ = prev_;
prev_->next_ = n;
prev_ = n;
}
void unlink() {
Node *next = next_, *prev = prev_;
next->prev_ = prev;
prev->next_ = next;
next_ = this;
prev_ = this;
}
};
在上面的例子中,节点
只需要两个操作就可以维护一个列表。除此之外,Node
本身就是一个最简单的列表,可以用于入侵列表(析构函数中有自动取消链接)。请注意如何使用此
检查nullptr
不必要-节点
始终是有效列表
错误检查应仅处于调试模式(例如,使用断言)。否则,这些检查将使用不必要的运行时检查来惩罚正确的应用程序
以下是一个基于您的想法的最小工作示例:
template<class T>
class List;
class Iterator;
class Node {
friend class Iterator;
template<class T> friend class List;
protected:
Node *next_, *prev_;
void push_back(Node* n) {
n->next_ = this;
n->prev_ = prev_;
prev_->next_ = n;
prev_ = n;
}
void unlink() {
Node *next = next_, *prev = prev_;
next->prev_ = prev;
prev->next_ = next;
next_ = this;
prev_ = this;
}
public:
Node()
: next_(this), prev_(this)
{}
~Node() { unlink(); }
};
class Iterator {
protected:
Node* node_;
Iterator(Node* node)
: node_(node)
{}
public:
Iterator& operator++() {
node_ = node_->next_;
return *this;
}
bool operator==(Iterator b) const { return node_ == b.node_; }
bool operator!=(Iterator b) const { return node_ != b.node_; }
// Implement the rest of iterator interface.
};
template<class T>
class List {
class NodeT : public Node {
friend class List<T>;
T value_;
NodeT(T t) : value_(t) {}
};
template<class U>
class IteratorT : public Iterator {
friend class List<T>;
NodeT* node() const { return static_cast<NodeT*>(node_); }
public:
U& operator*() const { return node()->value_; }
U* operator->() const { return &node()->value_; }
operator IteratorT<U const>() const { return node_; } // iterator to const_iterator conversion
IteratorT(Node* node) : Iterator{node} {}
};
Node list_;
public:
using iterator = IteratorT<T>;
using const_iterator = IteratorT<T const>;
~List() { clear(); }
bool empty() const { return list_.next_ == &list_; }
iterator begin() { return list_.next_; }
iterator end() { return &list_; }
void push_back(T t) { list_.push_back(new NodeT(t)); }
void erase(const_iterator i) { delete i.node(); }
void clear() {
while(!empty())
erase(begin());
}
// Implement the rest of the functionality.
};
int main() {
List<int> l;
l.push_back(1);
l.push_back(2);
l.push_back(3);
for(auto elem : l)
std::cout << elem << ' ';
std::cout << '\n';
}
模板
班级名单;
类迭代器;
类节点{
友元类迭代器;
模板好友类列表;
受保护的:
节点*下一个节点,*上一个节点;
无效推回(节点*n){
n->next=这个;
n->prev_uu=prev_uuu;
上一个->下一个=n;
prev_uun=n;
}
void unlink(){
节点*下一个=下一个,*上一个=上一个;
下一步->上一步=上一步;
上一步->下一步\下一步;
下一个=这个;
上一个=这个;
}
公众:
节点()
:下一个(这个),上一个(这个)
{}
~Node(){unlink();}
};
类迭代器{
受保护的:
Node*Node_;
迭代器(节点*节点)
:节点(node)
{}
公众:
迭代器和运算符++(){
节点=节点->下一步;
归还*这个;
}
布尔运算符==(迭代器b)常量{return node_==b.node_;}
布尔运算符!=(迭代器b)常量{return node_!=b.node_;}
//实现迭代器接口的其余部分。
};
样板
班级名单{
类节点集:公共节点{
好友类列表;
T值;
NodeT(T):值u(T){}
};
样板
类Iterator:公共迭代器{
好友类列表;
NodeT*node()常量{return static_cast(node_u);}
公众:
运算符*()常量{return node()->value_;}
U*运算符->()常量{return&node()->value_;}
运算符iterator()常量{返回节点}//迭代器到常量迭代器的转换
迭代器(Node*Node):迭代器{Node}{}
};
节点列表;
公众:
使用迭代器=迭代器;
使用常量迭代器=iterator;
~List(){clear();}
bool empty()常量{return list\.next\==&list\}
迭代器begin(){return list_u.next_u;}
迭代器end(){return&list}
void push_back(T){list_.push_back(new NodeT(T));}
void erase(常量迭代器i){delete i.node();}
无效清除(){
而(!empty())
擦除(begin());
}
//实现其余的功能。
};
int main(){
清单l;
l、 推回(1);
l、 推回(2);
l、 推回(3);
用于(自动元素:l)
std::cout 1/这很好。如果您最终使用具有类似迭代器实现的多个容器,那么将其分解出来可能是值得的。2/您不需要这样做(这是用户错误,不是正常的运行条件)。但是如果您愿意,(可能在调试版本中)然后考虑最后一个元素的<<代码>下一个>代码>指针。实际上,考虑一下,如果没有前哨节点,你将如何实现一个过去的迭代器。这可能是为你的需要而过度使用的方向,但是应该给你一些你可能想考虑的事情的想法。它目前是否有效?如果是,您最好将完整代码发布到CodeReview。那里的人非常擅长全面检查您的代码以找到可能的改进SideNote:您几乎肯定需要一个析构函数来清理,如果是这样,就会生效。@Tzalumen to learnsunlink()
在节点中是genius。但是节点是否应该有一个push\u back()
?非常感谢您所做的一切。@user644361取消链接
和推回
是所有其他操作所基于的两个低级基本操作。@user644361请注意,我没有用公共
和私有
节点::取消链接
和节点::推回
封装它只能通过列表
类访问。用户不应调用这些类