标签:
我使用vs2015写的程序(源码下载)
STL的中心思想在于将容器(container)和算法(algorithms)分开,彼此独立设计,最后再以一贴胶着剂将它们撮合在一起,而这个胶着剂就是迭代器(iterator)。
迭代器是访问容器的工具。注意,先有容器,才有访问容器的工具。迭代器需要了解容器的特性才能实现,这决定了迭代器必须要深入到容器内部,于是STL干脆把迭代器的开发交给容器的设计者。
迭代器的开发分为三步:
1. 元素的设计;
2. 装载元素的容器的设计;
3. 访问容器的迭代器的设计;
为了方便起见,我设计的是一款基于单向链表的迭代器。根据迭代器的开发步骤,首先给出链表节点的设计代码。
ListItem.h:
<pre name="code" class="cpp">#ifndef _CGH_LIST_ITEM_
#define _CGH_LIST_ITEM_
// 定义链表节点类型
template<typename T>
class ListItem{
public:
Tvalue() const{ return _value; }
ListItem*next() const{ return _next; }
ListItem(Tvalue) : _value(value), _next(NULL) { }
public:
T_value;
ListItem*_next;
};
#endif链表节点主要包含两个成员变量:
1. 保存节点值的_value;
2. 指向下一个节点的_next指针。
接下来是容器的设计,我开发的容器是单向链表,单向链表类的代码如下:
template<typename T>
class cghList{
public:
voidinsert_front(T value); // 插入节点到链表头部
voidinsert_end(T value); // 插入节点到链表尾部
voiddisplay(std::ostream& os = std::cout)const; // 从头到尾打印链表
cghList():_end(NULL), _front(NULL) { } // 构造函数,初始化头指针、尾指针
ListItem<T>*front()const{ return _front; } // 返回头指针
ListItem<T>*end()const{ return _end; } // 返回尾指针
private:
ListItem<T>*_end; // 链表尾指针
ListItem<T>*_front; // 链表头指针
long_size; // 链表长度
};单向链表的成员变量和成员函数的作用很简单,全是基本的链表操作。成员函数的实现不复杂,主要是对链表的头插和尾插。成员函数的实现代码如下。
// 插入节点到链表头部
template<typename T>
void cghList<T>::insert_front(T value){
cghList<T>::_size++;
ListItem<T>*tmp = new ListItem<T>(value);
if(typename cghList<T>::_front == NULL) {
typenamecghList<T>::_front = tmp;
typenamecghList<T>::_end = tmp;
}
else{
tmp->_next= _front;
_front= tmp;
}
}
// 插入节点到链表尾部
template<typename T>
void cghList<T>::insert_end(T value){
cghList<T>::_size++;
ListItem<T>*tmp = new ListItem<T>(value);
if(typename cghList<T>::_front == NULL) {
typenamecghList<T>::_front = tmp;
typenamecghList<T>::_end = tmp;
}
else{
typenamecghList<T>::_end->_next = tmp;
typenamecghList<T>::_end = typename cghList<T>::_end->_next;
}
}
//从头到尾打印链表
template<typename T>
void cghList<T>::display(std::ostream&os = std::cout)const{
if(typename cghList<T>::_front == NULL || typename cghList<T>::_end ==NULL){
return;
}
ListItem<T>*tmp = typename cghList<T>::_front;
while(tmp != NULL){
std::cout<< tmp->_value << std::endl;
tmp= tmp->_next;
}
}有了容器和容器的元素,接下来就是最关键的迭代器啦~
上代码:
cghIterator.h
#ifndef _CGH_ITERATOR_
#define _CGH_ITERATOR
template<typename Item>
struct ListIter : public std::iterator<std::forward_iterator_tag,Item>
{
Item*ptr; // 容器与迭代器的纽带
ListIter(Item*p = 0) :ptr(p) { } // 构造函数,初始化ptr指针
Item&operator*() const { return *ptr; } // 返回容器(本例为链表)的节点引用
Item*operator->() const { return ptr; } // 返回容器(本例为链表)的节点地址
// 指向容器(本例为链表)的下一个节点,i++
ListIter&operator++(){
ptr= ptr->next();
return*this;
}
// 指向容器(本例为链表)的下一个节点,++i
ListIter&operator++(int){
ListItertmp = *this;
++*this;
returntmp;
}
//判断两节点是否相等,也就是判断两节点的地址是否相同
booloperator==(const ListIter& i) const{
returnptr == i.ptr;
}
//判断两节点是否不相等,也就是判断两节点的地址是否不相同
booloperator!=(const ListIter& i) const{
returnptr != i.ptr;
}
};
#endif迭代器直接用struct定义的,而不是class,为什么呢?因为class的成员变量和成员函数默认是private访问权限,而struct的成员变量和成员函数默认是public访问权限。设计成struct也就是说任何人都可以使用迭代器的所有属性和功能。
本迭代器唯一也是最重要的成员成员变量是ptr指针,ptr其实就是ListItem*类型,是联系链表和迭代器的桥梁。
接下来是测试容器的代码:
// iterator.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cghList.h"
#include "cghIterator.h"
#include "ListItem.h"
#include<iostream>
int _tmain(int argc, _TCHAR* argv[])
{
cghList<int>myList; // 定义容器
//往容器中加入节点
for(int i = 0; i < 5; i++){
myList.insert_front(i);
}
//从前向后打印节点
//myList.display();
for(ListIter<ListItem<int>> iter = myList.front(); iter != myList.end();iter++){
std::cout<< iter->_value << std::endl;
}
system("pause");
return0;
}有了这个雏形,就可以往里面添砖加瓦了,有兴趣的童鞋可以在此基础上修改,写出自己的功能强大的迭代器!
标签:
原文地址:http://blog.csdn.net/chengonghao/article/details/51360792