为了向 STL 致敬(O(∩_∩)O~), 我们模仿STL中的list的迭代器, 我们也自己实现一个MyList的迭代器, 以供遍历整个链表的所有元素:

首先:Node节点需要做如下修改(注意后缀有+的代码)

//链表节点
template <typename Type>
class Node
{friend class MyList<Type>;friend class ListIterator<Type>; //+template <typename T>friend ostream &operator<<(ostream &os, const MyList<T> &list);
private:Node(const Type &dataValue):data(dataValue), next(NULL) {}Type data;  //数据域:节点数据Node *next; //指针域:下一个节点
};

然后:MyList类同样也需要做修改,但是由于MyList类过长, 修改之处也较少, 因此在此就不贴出, 完整代码会附到博客最后

ListIterator的设计

template <typename Type>
class ListIterator
{
public:ListIterator(const MyList<Type> &_list):list(_list),currentNode((_list.first)->next) {}//重载 *operatorconst Type &operator*() const throw (std::out_of_range);Type &operator*() throw (std::out_of_range);//重载 ->operatorconst Node<Type> *operator->() const throw (std::out_of_range);Node<Type> *operator->() throw (std::out_of_range);//重载 ++operatorListIterator &operator++() throw (std::out_of_range);//注意:此处返回的是值,而不是referenceListIterator operator++(int) throw (std::out_of_range);bool isEmpty() const;private:const MyList<Type> &list;Node<Type> *currentNode;
};

ListIterator类的实现

template <typename Type>
const Type &ListIterator<Type>::operator*() const
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");// 返回当前指针指向的内容return currentNode->data;
}template <typename Type>
Type &ListIterator<Type>::operator*()
throw (std::out_of_range)
{//首先为*this添加const属性,//以调用该函数的const版本,//然后再使用const_case,//将该函数调用所带有的const属性转除//operator->()的non-const版本与此类同returnconst_cast<Type &>(static_cast<const ListIterator<Type> &>(*this).operator*());
}
template <typename Type>
const Node<Type> *ListIterator<Type>::operator->() const
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");//直接返回指针return currentNode;
}template <typename Type>
Node<Type> *ListIterator<Type>::operator->()
throw (std::out_of_range)
{// 见上returnconst_cast<Node<Type> *> (static_cast<const ListIterator<Type> >(*this).operator->());
}
template <typename Type>
ListIterator<Type> &ListIterator<Type>::operator++()
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");//指针后移currentNode = currentNode->next;return *this;
}
template <typename Type>
ListIterator<Type> ListIterator<Type>::operator++(int)
throw (std::out_of_range)
{ListIterator tmp(*this);++ (*this); //调用前向++版本return tmp;
}
//判空
template <typename Type>
bool ListIterator<Type>::isEmpty() const
{if (currentNode == NULL)return true;return false;
}

附-ListIterator测试代码:

int main()
{std::list<int> iStdList;MyList<int>    iMyList;for (int i = 0; i < 10; ++i){iStdList.push_back(i+1);iMyList.insert(i+1, i+1);}for (std::list<int>::iterator iter = iStdList.begin();iter != iStdList.end();++ iter){cout << *iter << ' ';}cout << endl;for (ListIterator<int> iter(iMyList);!iter.isEmpty();++ iter){cout << *iter << ' ';}cout << endl;cout << "Test: \n\t" << iMyList << endl;ListIterator<int> iter(iMyList);
cout << "first = " << *iter << endl;
}

附-MyList完整源代码

//MyList.h
#ifndef MYLIST_H_INCLUDED
#define MYLIST_H_INCLUDED#include <iostream>
#include <stdexcept>
using namespace std;//前向声明
template <typename Type>
class MyList;
template <typename Type>
class ListIterator;//链表节点
template <typename Type>
class Node
{//可以将MyList类作为Node的友元//同时也可以将Node类做成MyList的嵌套类, 嵌套在MyList中, 也可以完成该功能friend class MyList<Type>;friend class ListIterator<Type>;template <typename T>friend ostream &operator<<(ostream &os, const MyList<T> &list);
private://constructor说明://next = NULL;    //因为这是一个新生成的节点, 因此下一个节点为空Node(const Type &dataValue):data(dataValue), next(NULL) {}Type data;  //数据域:节点数据Node *next; //指针域:下一个节点
};//链表
template <typename Type>
class MyList
{template <typename T>friend ostream &operator<<(ostream &os, const MyList<T> &list);friend class ListIterator<Type>;
public:MyList();~MyList();//将元素插入表头void insertFront(const Type &data);//将元素插入到位置index上(index从1开始)void insert(const Type &data, int index);//删除表中所有值为data的节点void remove(const Type &data);bool isEmpty() const;//链表反转void invort();//将链表(list)链接到本条链表的末尾void concatenate(const MyList<Type> &list);private://指向第一个节点的指针Node<Type> *first;
};template <typename Type>
MyList<Type>::MyList()
{//first指向一个空节点first = new Node<Type>(0);first -> next = NULL;
}
template <typename Type>
MyList<Type>::~MyList()
{Node<Type> *deleteNode = NULL;while (first != NULL){deleteNode = first;first = first -> next;delete deleteNode;}
}template <typename Type>
void MyList<Type>::insertFront(const Type &data)
{Node<Type> *newNode = new Node<Type>(data);newNode -> next = first -> next;first -> next = newNode;
}template <typename Type>
void MyList<Type>::insert(const Type &data, int index)
{//由于我们在表头添加了一个空节点//因此如果链表为空, 或者在链表为1的位置添加元素//其操作与在其他位置添加元素相同int count = 1;//此时searchNode肯定不为NULLNode<Type> *searchNode = first;// 找到要插入的位置// 如果所给index过大(超过了链表的长度)// 则将该元素插入到链表表尾// 原因是 searchNode->next != NULL 这个条件已经不满足了// 已经到达表尾while (count < index && searchNode->next != NULL){++ count;searchNode = searchNode->next;}// 插入链表Node<Type> *newNode = new Node<Type>(data);newNode->next = searchNode->next;searchNode->next = newNode;
}template <typename Type>
void MyList<Type>::remove(const Type &data)
{if (isEmpty())return ;Node<Type> *previous = first;   //保存要删除节点的前一个节点for (Node<Type> *searchNode = first->next;searchNode != NULL;searchNode = searchNode->next){if (searchNode->data == data){previous->next = searchNode->next;delete searchNode;//重新调整searchNode指针//继续遍历链表查看是否还有相等元素//如果当前searchNode已经到达了最后一个节点//也就是searchNode->next已经等于NULL了, 则下面这条语句不能执行if (previous->next == NULL)break;searchNode = previous->next;}previous = searchNode;}
}
template <typename Type>
bool MyList<Type>::isEmpty() const
{return first->next == NULL;
}template <typename Type>
void MyList<Type>::concatenate(const MyList<Type> &list)
{if (isEmpty())//如果自己的链表为空{first = list.first;return ;}else if (list.isEmpty())    //如果第二条链表为空{return ;}Node<Type> *endNode = first->next;//找到第一条链表的末尾节点while (endNode->next != NULL){endNode = endNode->next;}//找到第二条链表的第一个真实元素Node<Type> *secondListNode = (list.first)->next;//注意: 需要将第二个链表中的元素值copy出来//不能直接将第二条链表的表头链接到第一条链表的表尾//不然在析构函数回收内存时会发生错误(即:同一段内存释放两次)while (secondListNode != NULL){Node<Type> *newNode = new Node<Type>(secondListNode->data);newNode->next = NULL;endNode->next = newNode;//两条链表同时前进endNode = endNode->next;secondListNode = secondListNode->next;}
}template <typename Type>
void MyList<Type>::invort()
{if (!isEmpty()){//p指向正向链表的第一个真实节点//随后, p也会沿正方向遍历到链表末尾Node<Type> *p = first->next;//q会成为倒向的第一个真实节点//首先将q设置为NULL: 保证反向之后//最后一个元素的指针域指向NULL, 以表示链表结束Node<Type> *q = NULL;while (p != NULL){Node<Type> *r = q;  //暂存q当前指向的节点//q后退(沿着正向后退)q = p;//p前进(沿着正向前进), 保证p能够始终领先q一个位置p = p -> next;//将指针逆向反转//注意:一点要保证这条语句在p指针移动之后运行,//不然p就走不了了...(因为q改变了指针的朝向)q -> next = r;}//此时q成为反向链表的第一个真实元素//但是为了维护像以前一样的first指针指向一个无用的节点(以使前面的操作不会出错)//于是我们需要将first的指针域指向qfirst->next = q;}
}//显示链表中的所有数据(测试用)
template <typename Type>
ostream &operator<<(ostream &os, const MyList<Type> &list)
{for (Node<Type> *searchNode = list.first -> next;searchNode != NULL;searchNode = searchNode -> next){os << searchNode -> data;if (searchNode -> next != NULL) //尚未达到链表的结尾cout << " -> ";}return os;
}//ListIterator的设计与实现
template <typename Type>
class ListIterator
{
public:ListIterator(const MyList<Type> &_list):list(_list),currentNode((_list.first)->next) {}//重载 *operatorconst Type &operator*() const throw (std::out_of_range);Type &operator*() throw (std::out_of_range);//重载 ->operatorconst Node<Type> *operator->() const throw (std::out_of_range);Node<Type> *operator->() throw (std::out_of_range);//重载 ++operatorListIterator &operator++() throw (std::out_of_range);//注意:此处返回的是值,而不是referenceListIterator operator++(int) throw (std::out_of_range);bool isEmpty() const;private:const MyList<Type> &list;Node<Type> *currentNode;
};template <typename Type>
const Type &ListIterator<Type>::operator*() const
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");// 返回当前指针指向的内容return currentNode->data;
}
template <typename Type>
Type &ListIterator<Type>::operator*()
throw (std::out_of_range)
{//首先为*this添加const属性,//以调用该函数的const版本,//然后再使用const_case,//将该函数调用所带有的const属性转除//operator->()的non-const版本与此类同returnconst_cast<Type &>(static_cast<const ListIterator<Type> &>(*this).operator*());
}template <typename Type>
const Node<Type> *ListIterator<Type>::operator->() const
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");//直接返回指针return currentNode;
}template <typename Type>
Node<Type> *ListIterator<Type>::operator->()
throw (std::out_of_range)
{// 见上returnconst_cast<Node<Type> *> (static_cast<const ListIterator<Type> >(*this).operator->());
}template <typename Type>
ListIterator<Type> &ListIterator<Type>::operator++()
throw (std::out_of_range)
{if (isEmpty())throw std::out_of_range("iterator is out of range");//指针前移currentNode = currentNode->next;return *this;
}
template <typename Type>
ListIterator<Type> ListIterator<Type>::operator++(int)
throw (std::out_of_range)
{ListIterator tmp(*this);++ (*this); //调用前向++版本return tmp;
}
template <typename Type>
bool ListIterator<Type>::isEmpty() const
{if (currentNode == NULL)return true;return false;
}#endif // MYLIST_H_INCLUDED

数据结构基础(10) --单链表迭代器的设计与实现相关推荐

  1. python数据结构基础(单链表,多链表,二叉树)

    python数据结构基础(单链表,多链表,二叉树) 数据结构指数据对象中数据元素之间的关系 Python 给我们提供了很多现成的数据结构类型,这些系统自己定义好的,不需要我们自己去定义的数据结构叫做 ...

  2. 数据结构基础(8) --单链表的设计与实现(1)之基本操作

    链表简介 数组的缺点: 1.元素插入:除了在数组的末尾插入元素之外,在数组的其他任何位置插入元素都需要进行数组元素的频繁移动(插入位置之后的元素都需往后移动), 时间复杂度约为O(N); 2.数组的删 ...

  3. 数据结构基础(9) --单链表的设计与实现(2)之高级操作

    链表的链接: 将第二条链表的所有内容链接到第一条链表之后, 其完整实现代码与解析如下: //链表的链接 template <typename Type> void MyList<Ty ...

  4. 数据结构精讲——单链表

    新手必会数据结构精讲--单链表 链表的介绍 概念:链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 . 实际中链表的结构非常多样,以下情况组合起来就 ...

  5. 数据结构之——《单链表》

    数据结构之--<单链表> 1.链表概念 2.链表分类 3.接口函数实现 1.链表概念 链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现. ...

  6. 数据结构与算法--单链表相关面试题

    此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.概述 获取单链表的有效元素个数[新浪面试题1] 获取单链表倒数第k个结 ...

  7. 【数据结构系列】单链表

    专栏介绍 最近也一直在思考该写点什么文章,想了很久,还是决定重新编写一下数据结构的相关内容,关于数据结构的重要性就不用我多说了,之前的文章中我也写过,但实现语言是Java.其实对于数据结构的学习,最好 ...

  8. 头歌平台数据结构与算法 单链表实验 第1关:倒置链表

    任务描述 相关知识 实验目的 实验任务 实验说明 编程要求 测试说明 任务描述 本关任务:请在右侧编辑器的注释行填入适当内容来完成算法,以实现指定的功能,并通过运行来验证. 相关知识 实验目的 理解线 ...

  9. [数据结构与算法] 单链表的简单demo

    Vc6之下编译通过.. 1 /******************************************************* 2 * @: Project: 单链表数据结构演示 3 * ...

最新文章

  1. python操作符笔记
  2. django 使用Ajax方式POST JSON数据包
  3. boost::mpl模块实现identity相关的测试程序
  4. Spring模板对象之RedisTemplate(Spring整合jedis)
  5. flash调用js中的方法,让js传递变量给flash (兼容 IE FF) (转)
  6. msgpack java lua_使用lua-cmsgpack序列化和反序列化lua对象
  7. 运用Axure6.5快速完成微信交互效果的简单办法
  8. USB-IF 再度为 USB 3 改名,这次更难辨别了
  9. request.getcontextPath() 详解(转)
  10. 多目标优化问题和遗传算法学习
  11. linux关闭端口命令_linux 网络检测常用命令(tcp/udp 端口检测)
  12. 【Android 应用开发】GitHub 优秀的 Android 开源项目
  13. 华丽成长为IT高富帅、IT白富美(五)
  14. 游戏常用数据分析指标汇总
  15. java exception message_Java 如何摆脱Exception.getMessage()输出带类名
  16. 平行时代的平行智能体系(王飞跃)
  17. 苹果手机无线网显示无网络连接到服务器,iPhone提示:“无线局域网似乎未接入互联网”,咋回事?...
  18. Outlook邮箱满了不用删除清理,快速转移保存到本地
  19. windows启动引导管理
  20. LEADTOOLS V22.0 Patch

热门文章

  1. (王道408考研操作系统)第一章计算机系统概述-第一节3:操作系统的运行机制与体系结构
  2. protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用
  3. 浅析 Linux 初始化 init 系统,第 3 部分: Systemd
  4. c++程序设计中文件输入输出流知识点
  5. Python subprocess.check_output 执行shell命令 返回结果(单次执行shell命令)
  6. python类及其方法
  7. 安装redisclient、redis-cluster,使用redis desktop manager和java(eclipse)连接redis过程遇到问题汇总
  8. python ThreadPoolExecutor线程池(实例)
  9. 编程学习记录13:Oracle数据库,表的查询
  10. RequireJS模块化之循环依赖