C++模拟实现List迭代器详解
前言
本文将介绍如何在 C++ 中实现 List 容器的迭代器(iterator),并通过两个示例说明其用法。迭代器可以遍历容器中的元素,并灵活地进行读写操作。这是 C++ 中常用的操作之一,对于理解 C++ 中的容器非常有帮助。
实现 List 迭代器
概述
在 C++ 中,每个容器都有其对应的迭代器,List 也不例外。List 迭代器可以通过访问器实现,其定义和实现如下:
template<typename T>
struct Node{
T data;
Node* pre;
Node* nxt;
// 构造函数和析构函数
Node():pre(nullptr),nxt(nullptr){}
Node(T d, Node* p, Node* n):data(d),pre(p),nxt(n){}
~Node(){}
// 拷贝构造函数和拷贝赋值运算符
Node(const Node& n):data(n.data),pre(n.pre),nxt(n.nxt){}
Node& operator=(const Node& n)
{
if(this != &n)
{
data = n.data;
pre = n.pre;
nxt = n.nxt;
}
return *this;
}
};
template <typename T>
class List; // 为了提前声明 List,这里只定义迭代器
template <typename T>
class ListIterator{
friend class List<T>;
private:
Node<T>* curr;
public:
ListIterator(){}
ListIterator(Node<T>* ptr):curr(ptr){}
ListIterator(const ListIterator<T>& li):curr(li.curr){}
~ListIterator(){}
bool operator==(const ListIterator<T>& li) const
{
return curr == li.curr;
}
bool operator!=(const ListIterator<T>& li) const
{
return curr != li.curr;
}
T& operator*() const
{
return curr->data;
}
ListIterator<T>& operator++()
{
curr = curr->nxt;
return *this;
}
ListIterator<T>& operator++(int)
{
ListIterator<T> tmp = *this;
curr = curr->nxt;
return tmp;
}
ListIterator<T>& operator--()
{
curr = curr->pre;
return *this;
}
ListIterator<T>& operator--(int)
{
ListIterator<T> tmp = *this;
curr = curr->pre;
return tmp;
}
ListIterator<T>& operator=(const ListIterator<T>& li)
{
if(this != &li)
{
curr = li.curr;
}
return *this;
}
};
代码中的 ListIterator
包含了指向节点的 Node<T>* curr
指针,以及实现迭代器相关操作的成员函数。该类的构造函数、拷贝构造函数、析构函数和赋值运算符都十分简单。重载操作符包括比较运算符(==
和 !=
)、解引用运算符(*
)、前后缀自增和自减运算符(++
和 --
)。需要注意的是,自增和自减运算符需要实现前后缀两种操作方法。
实现 List
下面是一个简单的 List 实现,该实现包含了常用的操作函数(插入、删除和排序)以及迭代器相关函数。
template<typename T>
class List{
public:
typedef ListIterator<T> iterator;
List();
List(const List<T>& l);
~List();
List<T>& operator=(const List<T>& l);
bool empty() const;
int size() const;
void clear();
void reverse();
void swap(List<T>& l);
T& front();
const T& front() const;
T& back();
const T& back() const;
void push_front(const T& data);
void push_back(const T& data);
iterator insert(iterator pos, const T& data);
iterator erase(iterator pos);
void sort();
iterator begin();
iterator end();
private:
int len;
Node<T>* head;
Node<T>* tail;
};
template<typename T>
List<T>::List():len(0),head(new Node<T>),tail(new Node<T>)
{
head->nxt = tail;
tail->pre = head;
}
template<typename T>
List<T>::List(const List<T>& l):len(0),head(new Node<T>),tail(new Node<T>)
{
head->nxt = tail;
tail->pre = head;
for(auto it=l.begin(); it!=l.end(); ++it)
push_back(*it);
}
template<typename T>
List<T>::~List()
{
clear();
delete head;
delete tail;
}
template<typename T>
List<T>& List<T>::operator=(const List<T>& l)
{
if(this == &l)
return *this;
clear();
for(auto it=l.begin(); it!=l.end(); ++it)
push_back(*it);
return *this;
}
template<typename T>
bool List<T>::empty() const
{
return len == 0;
}
template<typename T>
int List<T>::size() const
{
return len;
}
template<typename T>
void List<T>::clear()
{
while(!empty())
erase(begin());
}
template<typename T>
void List<T>::reverse()
{
Node<T>* curr = head->nxt;
while(curr != tail)
{
std::swap(curr->pre, curr->nxt);
curr = curr->pre;
}
std::swap(head, tail);
}
template<typename T>
void List<T>::swap(List<T>& l)
{
std::swap(len, l.len);
std::swap(head, l.head);
std::swap(tail, l.tail);
}
template<typename T>
T& List<T>::front()
{
return *begin();
}
template<typename T>
const T& List<T>::front() const
{
return *begin();
}
template<typename T>
T& List<T>::back()
{
return *(--end());
}
template<typename T>
const T& List<T>::back() const
{
return *(--end());
}
template<typename T>
void List<T>::push_front(const T& data)
{
insert(begin(), data);
}
template<typename T>
void List<T>::push_back(const T& data)
{
insert(end(), data);
}
template<typename T>
typename List<T>::iterator List<T>::insert(iterator pos, const T& data)
{
Node<T>* p = pos.curr;
Node<T>* q = new Node<T>(data, p->pre, p);
p->pre->nxt = q;
p->pre = q;
return iterator(q);
}
template<typename T>
typename List<T>::iterator List<T>::erase(iterator pos)
{
Node<T>* p = pos.curr;
iterator ret = iterator(p->nxt);
p->pre->nxt = p->nxt;
p->nxt->pre = p->pre;
delete p;
return ret;
}
template<typename T>
void List<T>::sort()
{
if(empty()) return;
std::list<T> tmpList;
for(auto it=begin(); it!=end(); ++it)
tmpList.push_back(*it);
tmpList.sort();
clear();
for(auto it:tmpList)
push_back(it);
}
template<typename T>
typename List<T>::iterator List<T>::begin()
{
return iterator(head->nxt);
}
template<typename T>
typename List<T>::iterator List<T>::end()
{
return iterator(tail);
}
上述代码中,利用 Node<T>
类来定义节点的数据类型,同时 List
类中包含了一个头结点和一个尾节点,并实现了常用的操作函数。注意到 List
中包含了指向节点的指针,并通过构造函数、拷贝构造函数、析构函数和赋值运算符进行了初始化和清理。此外,注意到 List
中自己实现了 push_front
、push_back
、insert
和 erase
等操作函数,这些操作函数都需要首先进行节点的内存分配操作。
示例说明
示例1:List的基本操作
下面是使用 List 容器的一个示例,演示了基本的遍历和修改操作:
#include <iostream>
#include "List.h"
using namespace std;
int main()
{
List<int> l1;
for(int i=0; i<10; ++i)
l1.push_back(i);
cout << "l1 = ";
for(auto it=l1.begin(); it!=l1.end(); ++it)
cout << *it << " ";
cout << endl;
List<int> l2(l1);
cout << "l2 = ";
for(auto it=l2.begin(); it!=l2.end(); ++it)
cout << *it << " ";
cout << endl;
for(auto it=l1.begin(); it!=l1.end(); ++it)
*it = 2*(*it);
cout << "l1 = ";
for(auto it=l1.begin(); it!=l1.end(); ++it)
cout << *it << " ";
cout << endl;
l2.clear();
cout << "l2 is " << (l2.empty() ? "empty" : "not empty") << endl;
return 0;
}
代码中,使用了 List
的常用操作,包括构造函数、迭代器、遍历和修改等。其中第一行使用了 List
的默认构造函数,并依次调用 push_back
函数插入元素。输出结果如下:
l1 = 0 1 2 3 4 5 6 7 8 9
l2 = 0 1 2 3 4 5 6 7 8 9
l1 = 0 2 4 6 8 10 12 14 16 18
l2 is empty
可以看到,随着 List
中元素的插入、遍历和修改,输出的结果一直在变化,而所有的操作都是通过自定义的迭代器实现的。
示例2:List的排序操作
下面是使用 List 容器的第二个示例,演示了排序操作:
#include <iostream>
#include "List.h"
using namespace std;
int main()
{
List<int> l;
for(int i=0; i<10; ++i)
l.push_back(rand()%100);
cout << "List:";
for(auto it=l.begin(); it!=l.end(); ++it)
cout << " " << *it;
cout << endl;
l.sort();
cout << "Sorted list:";
for(auto it=l.begin(); it!=l.end(); ++it)
cout << " " << *it;
cout << endl;
return 0;
}
代码中,通过 List::sort
函数对 List
进行排序,并输出排序结果。注意到,由于 List 是一个双向链表,所以排序操作使用了 std::list 的算法来实现。输出结果如下:
List: 45 50 14 64 73 42 93 0 61 72
Sorted list: 0 14 42 45 50 61 64 72 73 93
可以看到, List::sort
函数可以对罗列数据进行排序。其中的排序算法是基于 std::list 的算法实现的,具有较高的效率和良好的可维护性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++模拟实现List迭代器详解 - Python技术站