为了提高C++编程的效率,STL中提供了许多容器,包括vector、list、map等。为了统一访问方式,STL为每种容器在实现的时候设计了一个内嵌的iterator类,不同的容器有自己专属的迭代器,使用迭代器来访问容器中的数据。迭代器对一些基本操作如*、–、++、==、!=进行了重载,使其具有了遍历复杂数据结构的能力,其遍历机制取决于所遍历的容器,迭代器的使用和指针的使用非常相似。通过begin,end函数获取容器的头部和尾部迭代器,当begin和end返回的迭代器相同时表示容器为空。简单来说,迭代器就是一个遍历的过程,像使用指针一样使用迭代器就可以访问这个容器。
定义一个迭代类所需要的操作:
这里我们使用一下之前我写过的一个链表容器来辅助实现:
class iterator//迭代类
{
private:
node* m_start;//起始指向
node* m_cur;//现在指向
node* m_end;//中止指向
public:
iterator(node* start, node* cur, node* end): m_start(start), m_cur(cur), m_end(end){}
T& operator*() {//重载*运算符
if (m_cur == nullptr)
throw underflow_error("链表为空。");//抛出异常
else
return m_cur->m_data;
}
//重载++运算符
iterator& operator++() {
if (m_cur == nullptr)
m_cur = m_start;
else
m_cur = m_cur->m_next;
return *this;
}
//重载--运算符
iterator& operator--() {
if (m_cur == nullptr)
m_cur = m_tail;
else
m_cur = m_cur->pre;
return *this;
}
//重载==运算符
bool operator==(const iterator& that)const {
return m_start == that.m_start && m_cur == that.m_cur && m_end == that.m_end;
}
//重载!=运算符
bool operator!=(const iterator & that)const {
return !(*this == that);
}
friend class list;
};
这个迭代类是定义在链表容器类里面的成员类,下面总代码中就知道了。
//创建迭代器
iterator begin() {
return iterator(m_head, m_head, m_tail);
}
//创建第二个迭代器
iterator end() {
return iterator(m_head, nullptr, m_tail);
}
这样我们只要创建一个容器的对象来调用这两个函数就产生两个迭代器了,然后用迭代类里面的重载运算符就可以使用迭代器遍历容器了。
查找很简单,遍历判断就行了:
template<class IT, class TD>
IT find(const IT &begin, const IT &end, const TD& number)
{
for (IT it = begin; it != end; ++it)
{
if (*it == number)
return it;
}
return end;
}
我们要为一个容器写一个排序函数对容器进行排序。
我们采用快速排序的方式,那我们先来讲一下什么是快速排序:
排序("<")
template<class IT>
void sort(const IT& begin, const IT& end)
{
IT p = begin;
IT last = end;
--last;
for (IT i = begin, j = last; i != j;)
{
while (i != p && *i < *p)//两个变量不相等并且i
++i;
if (i != p)
{
swap(*i, *p);
p = i;
}
while (j != p && *p < *j)
--j;
if (j != p)
{
swap(*p, *j);
p = j;
}
}
IT be = begin;
++be;
if (p != begin && p != be)
sort(begin, p);//递归左边
be = p;
++be;
if (be != end && be!= last)
sort(be, end);//递归右边
}
代码可能有点烂,但能力之内了,请见谅。
但我们这样的话就只能升序了,而如果想要降序的话就还需要重新写一个函数,这样的话就非常麻烦,所以我们可以实现一个比较器来配合着上面这个代码,就相当于进行了一个优化。
比较器:简单来说就是一个类,制造容器的人不负责制造比较器这个类,需要用户自己来定义一个这样的类。
//一个简单的比较器
lass MSD
{
public:
bool operator()(int a, int b) {
return a > b;//可以是大于或小于
}
};
//排序(比较器)
template<class IT, class MSD>//MSD是一个类
void sort(const IT& begin, const IT& end, MSD msd)
{
IT p = begin;
IT last = end;
--last;
for (IT i = begin, j = last; i != j;)
{
while (i != p && msd(*i, *j))
++i;
if (i != p)
{
swap(*i, *p);
p = i;
}
while (j != p && msd(*p, *j))
--j;
if (j != p)
{
swap(*p, *j);
p = j;
}
}
IT be = begin;
++be;
if (p != begin && p != be)
sort(begin, p, msd);
be = p;
++be;
if (be != end && be != last)
sort(be, end, msd);
}
#include
using namespace std;
template<typename T>
class list
{
private:
class node//节点
{
public:
node(const T &data, node * p, node* n): m_data(data),m_pre(p), m_next(n){}
T m_data;
node* m_pre;//前驱
node* m_next;//后继
};
node* m_head;//链表头节点
node* m_tail;//链表未节点
public:
class iterator
{
private:
node* m_start;//起始指向
node* m_cur;//现在指向
node* m_end;//中止指向
public:
iterator(node* start, node* cur, node* end): m_start(start), m_cur(cur), m_end(end){}
T& operator*() {//重载*运算符
if (m_cur == nullptr)
throw underflow_error("链表为空。");//抛出异常
else
return m_cur->m_data;
}
//重载++运算符
iterator& operator++() {
if (m_cur == nullptr)
m_cur = m_start;
else
m_cur = m_cur->m_next;
return *this;
}
//重载--运算符
iterator& operator--() {
if (m_cur == nullptr)
m_cur = m_end;
else
m_cur = m_cur->pre;
return *this;
}
//重载==运算符
bool operator==(const iterator& that)const {
return m_start == that.m_start && m_cur == that.m_cur && m_end == that.m_end;
}
//重载!=运算符
bool operator!=(const iterator & that)const {
return !(*this == that);
}
friend class list;
};
//创建迭代器
iterator begin() {
return iterator(m_head, m_head, m_tail);
}
//创建第二个迭代器
iterator end() {
return iterator(m_head, nullptr, m_tail);
}
//利用迭代器添加元素
void add(iterator& that, const T &num)
{
if (that == end())
push_back(num);
else
{
node* p = new node(num, that.m_cur->m_pre, that.m_cur);
if (that.m_cur->m_pre)
that.m_cur->m_pre->m_next = p;
else
m_head = p;
p->m_next->m_pre = p;
}
}
//删除元素
void eares(iterator& that)
{
if (that == end())
return;
node* p = that.m_cur;
if (p->m_pre)
p->m_pre->m_next = p->m_next;
else
m_head = p->m_next;
if (p->m_next)
p->m_next->m_pre = p->m_pre;
else
m_tail = p->m_pre;
delete p;
}
//缺省构造
list():m_head(nullptr), m_tail(nullptr){}
//复制构造
list(const list& that) {
for (node* p = that.m_head; p; p = p->m_next)
push_back(p->m_data);
}
//析构函数
~list() {
clear();
}
//判断链表是否为空
bool empty() {
return m_head == nullptr && m_tail == nullptr;
}
//链表清空
void clear() {
while (!empty())
pop_prent();
}
//添加头节点
void push_prent(const T & data) {
m_head = new node(data, nullptr, m_head);
if (m_head->m_next)
m_head->m_next->m_pre = m_head;
else
m_tail = m_head;
}
//删除头节点
void pop_prent() {
if (empty())
return;
node* ponde = m_head->m_next;
delete m_head;
if (ponde)
ponde->m_pre = nullptr;
else
m_tail = nullptr;
m_head = ponde;
}
//添加未节点
void push_back(const T& data) {
m_tail = new node(data, m_tail, nullptr);
if (m_tail->m_pre)
m_tail->m_pre->m_next = m_tail;
else
m_tail = m_head;
}
//删除尾节点
void pop_back() {
if (empty())
return;
node* ponde = m_tail->m_pre;
delete m_tail;
if (ponde)
ponde->m_next = nullptr;
else
m_head = nullptr;
m_tail = ponde;
}
//获取链表头元素
T& get_prent() {
if (empty())
throw underflow_error("链表为空。");//抛出异常
return m_head->m_data;
}
const T& get_prent() const {
return const_cast<list*>(this)->get_prent();
}
//获取链表未元素
T& get_back() {
if(empty())
throw underflow_error("链表为空。");//抛出异常
return m_tail->m_data;
}
const T& get_back()const {
return const_cast<list*>(this)->get_back();
}
//获取链表大小
size_t get_size() {
size_t i = 0;
for (node* p = m_head; p; p = p->m_next)
++i;
return i;
}
};
//利用迭代器遍历打印
void print(list<int> & ls)
{
using IT = list<int>::iterator;
for (IT it = ls.begin(); it != ls.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
//查找
template<class IT, class TD>
IT find(const IT &begin, const IT &end, const TD& number)
{
for (IT it = begin; it != end; ++it)
{
if (*it == number)
return it;
}
return end;
}
//一个简单的比较器
lass MSD
{
public:
bool operator()(int a, int b) {
return a > b;//可以是大于或小于
}
};
//排序(比较器)
template<class IT, class MSD>//MSD是一个类
void sort(const IT& begin, const IT& end, MSD msd)
{
IT p = begin;
IT last = end;
--last;
for (IT i = begin, j = last; i != j;)
{
while (i != p && msd(*i, *j))
++i;
if (i != p)
{
swap(*i, *p);
p = i;
}
while (j != p && msd(*p, *j))
--j;
if (j != p)
{
swap(*p, *j);
p = j;
}
}
IT be = begin;
++be;
if (p != begin && p != be)
sort(begin, p, msd);
be = p;
++be;
if (be != end && be != last)
sort(be, end, msd);
}
//代码实现
//-----------------------------
//代码使用
int main()
{
list<int> ls;
for (int i = 0; i < 5; i++)
ls.push_prent(10 + i);
for (int i = 0; i < 5; i++)
ls.push_back(100 + i);
print(ls);
using IT = list<int>::iterator;
IT it = ls.begin();
ls.eares(it);//删除it所指向的节点
print(ls);
cout << "--------------------" << endl;
IT ib = ls.begin();
ls.add(++ib, 120);//添加节点到第二位置
print(ls);
cout << "---------" << endl;
cout << "找到一个数并删除它:" << endl;
IT its = finds(ls.begin(), ls.end(), 100);
if (its != ls.end())
ls.eares(its);
print(ls);
cout << "-----排序-----" << endl;
MSD msd;
sort(ls.begin(), ls.end(), msd);
print(ls);
return 0;
}
可能说的有点不好,但需要你学习关于链表的知识才能搞清楚这个知识。