用迭代器构建的单链表
2007-11-25 20:15
399 查看
所谓单链表的迭代器,就是将原本链表中用于处理遍历、访问和更新的方法封装到一个新的迭代器类中,而只在链表类中保留描述其状态的成员函数。在讨论其实现方法和特点之前,先看一下是如何使用的。
//Main.cpp
#include "AbsList.cpp"
#include "AbsListItr.cpp"
#include "ListNode.cpp"
#include "List.cpp"
#include "ListItr.cpp"
int main()
...{
List<int> list; //定义一个单链表
cout<<list.IsEmpty()<<endl; //判断是否为空
ListItr<int> itr(list); //定义一个迭代器
for(int i=1;i<=10;i++)
itr.Insert(i); //插入10个元素
cout<<itr()<<endl; //输出当前结点的元素
cout<<itr.Remove(5)<<endl; //删除值为5的结点
cout<<list<<endl; //输出整个链表
return 0;
}
从中不难看出,绝大多数对链表的处理是通过迭代器来完成的(事实上最后的输出整个链表也是如此)。那么为何在main()中,一个迭代器对象能处理一个链表对象呢,看起来它们的“地位”似乎是一样的。请注意上述代码中的第五行:List<int> itr(list); 在定义一个迭代器 itr 时,需要将一个链表对象 list 作为参数传递给迭代器类的构造函数。迭代器类和链表类一样有一个头指针,利用链表结点的特性,在迭代器类的构造函数中,通过把链表的头指针赋给迭代器的头指针,使得它们同时指向链表的头结点,迭代器就能访问整个链表了。
以下是具体实现的代码,参考自《数据结构与算法(C++)》 2005 上海交通大学出版社 窦延平 张同珍 姜丽红 陈玉泉。(这本书我很不推荐)
链表类:
//AbsList.cpp
#define ABSLIST
#ifndef ABSLISTITR
template <class ElemType> class AbsListItr;
#endif //ABSLISTITR
template <class ElemType>
class AbsList
...{
public:
AbsList()...{}
virtual ~AbsList()...{}
virtual IsEmpty() const=0; //是否空
virtual IsFull() const=0; //是否满
virtual void MakeEmpty()=0; //清空
friend class AbsListItr<ElemType>;
private:
AbsList(const AbsList &)...{} //冻结复制另一链表的构造函数
};
链表迭代器类:
//AbsListItr.cpp
#define ABSLISTITR
#ifndef ABSLIST
template <class ElemType> class AbsList;
#endif //ABSLIST
template <class ElemType>
class AbsListItr
...{
public:
AbsListItr(const AbsList<ElemType> &L)...{}
AbsListItr(const AbsListItr&);
virtual ~AbsListItr()...{}
virtual void Insert(const ElemType &x)=0; //在当前结点后插入
virtual int Remove(const ElemType &x)=0; //删除值为x的结点
virtual int Find(const ElemType &x)=0;
virtual int IsFound(const ElemType &x) const=0;
virtual int operator+() const=0; //判断当前结点是否存在
virtual const ElemType & operator()()const=0; //取当前结点的内容
virtual void Zeroth()=0; //定位于链表的首结点之前
virtual void First()=0; //定位于链表的首结点
virtual void operator++()=0; //定位于下一结点
virtual void operator ++(int)=0;
protected:
AbsListItr()...{} //冻结无参数的构造函数
};
单链表结点类:
//ListNode.cpp
#include <iostream.h>
#ifndef LISTNODE
#define LISTNODE
#ifndef LIST
template<class ElemType> class List;
#endif //LIST
#ifndef LISTITR
template<class ElemType> class ListItr;
#endif //LISTITR
template<class ElemType>
class ListNode
...{
friend class List<ElemType>;
friend class ListItr<ElemType>;
private:
ListNode<ElemType> *Next;
ElemType Element;
public:
ListNode(const ElemType &E,ListNode<ElemType> *N=NULL):Element(E),Next(N)...{}
ListNode()...{Next=NULL;}
~ListNode()...{};
};
#endif //LISTNODE
单链表类:
//List.cpp
#define LIST
#include <iostream.h>
#ifndef ABSLIST
template<class ElemType> class AbsList;
#endif //ABSLIST
#ifndef LISTITR
template<class ElemType> class ListItr;
#endif //LISTITR
#ifndef LISTNODE
template<class ElemType> class ListNode;
#endif //LISTNODE
template<class ElemType>
class List:public AbsList<ElemType>
...{
friend class ListItr<ElemType>;
private:
ListNode<ElemType> *head;
public:
List()
...{
head=new ListNode<ElemType>;
}
~List()
...{
MakeEmpty();
delete head;
}
const List &operator=(const List &R);
int IsEmpty() const
...{
return head->Next==NULL;
}
int IsFull()const
...{
return 0;
}
void MakeEmpty();
};
template <class ElemType>
void List<ElemType>::MakeEmpty()
...{
ListNode<ElemType> *Ptr;
ListNode<ElemType> *NextNode;
for(Ptr=head->Next;Ptr!=NULL;Ptr=NextNode)
...{
NextNode=Ptr->Next;
delete Ptr;
}
head->Next=NULL;
}
template <class ElemType>
const List<ElemType> & List<ElemType>::operator=(const List<ElemType> &R)
...{
if(this==&R)
return *this;
MakeEmpty();
ListItr<ElemType> Itr(*this);
for(ListItr<ElemType> Ritr(R);+Ritr;Ritr++)
Itr.Insert(Ritr());
return *this;
}
template <class ElemType>
ostream & operator<<(ostream & Out,const List<ElemType> &L)
...{
if(L.IsEmpty())
Out<<"Empty List";
else
for(ListItr<ElemType> Itr(L);+Itr;Itr++)
Out<<Itr()<<endl;;
return Out;
}
迭代器类:
//ListItr.cpp
#define LISTITR
#ifndef ABSLISTITR
template<class ElemType> class AbsListItr;
#endif //ABSLISTITR
#ifndef LISTNODE
template<class ElemType> class ListNode;
#endif //LISTNODE
#ifndef LIST
template<class ElemType> class List;
#endif //LIST
template<class ElemType>
class ListItr:public AbsListItr<ElemType>
...{
private:
ListNode<ElemType> *const head;
ListNode<ElemType> *Current;
public:
ListItr(const List<ElemType> &L):head(L.head)
...{
Current=L.IsEmpty() ? head : head->Next;
}
~ListItr()...{}
int Find(const ElemType &x); //查找值为x的结点,成功则使其成为当前结点
int IsFound(const ElemType &x) const; //查找值为x的结点,不改变Current
void Insert(const ElemType &x);
int Remove(const ElemType &x);
int operator +() const //当前结点非空则返回True
...{
return Current && Current !=head;
}
const ElemType & operator()()const; //取当前结点的数据值
void operator ++(); //使当前结点的后继结点成为当前结点 前缀++
void operator ++(int) //将后缀++定义为前缀++
...{
operator++();
}
void Zeroth()
...{
Current=head;
}
void First();
const ListItr & operator=(const ListItr&); //赋值运算符
};
template<class ElemType>
void ListItr<ElemType>::Insert(const ElemType &x)
...{
ListNode<ElemType> *p;
p=new ListNode<ElemType>(x,Current->Next);
Current=Current->Next=p;
}
template<class ElemType>
int ListItr<ElemType>::Find(const ElemType &x)
...{
ListNode<ElemType> *Ptr=head->Next;
while(Ptr!=NULL && !(Ptr->Element==x))
Ptr=Ptr->Next;
if(Ptr==NULL)
return 0;
Current=Ptr;
return 1;
}
template<class ElemType>
int ListItr<ElemType>::IsFound(const ElemType &x) const
...{
ListNode<ElemType> *Ptr=head->Next;
while(Ptr!=NULL && !(Ptr->Element==x))
Ptr=Ptr->Next;
return Ptr!=NULL;
}
template<class ElemType>
int ListItr<ElemType>::Remove(const ElemType &x)
...{
ListNode<ElemType> *Ptr=head;
while(Ptr->Next!=NULL && !(Ptr->Next->Element==x))
Ptr=Ptr->Next;
if(Ptr->Next==NULL)
return 0;
ListNode<ElemType> *P=Ptr->Next;
Ptr->Next=Ptr->Next->Next;
delete P;
Current=head;
return 1;
}
template<class ElemType>
const ElemType & ListItr<ElemType>::operator()()const
...{
return Current->Element;
}
template<class ElemType>
void ListItr<ElemType>::operator++()
...{
Current=Current->Next;
}
template<class ElemType>
const ListItr<ElemType> &ListItr<ElemType>::operator=(const ListItr<ElemType> &R)
...{
if(this==&R)
return *this;
head=R.head;
Current=R.Current;
return *this;
}
template<class ElemType>
void ListItr<ElemType>::First()
...{
Current=head->Next;
}
细心的人肯定已经发现了,要使迭代器能够访问链表的头指针,必须将迭代器类设为链表类的友元类,这在一定程度上破坏了类的封装性。使用迭代器的初衷是未避免经常修改链表类以及链表类变的过于庞大。然而面向对象程序设计的一个基本原则是封装性和信息隐蔽。友元类虽然有助于数据共享,却违背了信息隐蔽,一般只有在使用它时能使程序精炼并能大大提高程序的效率时才使用友元。
很显然,在构建链表时使用迭代器使程序变的复杂,不利于初学者把精力放在数据结构本身上。同时以破坏封装性为代价,在小规模程序中并没有提高程序的效率(反而是降低了)。因此我建议初学者在学习数据结构时不要使用迭代器。
可以通过此链接下载本程序:http://cid-24fba8dfcc188fae.skydrive.live.com/self.aspx/Public/ListItr.rar
//Main.cpp
#include "AbsList.cpp"
#include "AbsListItr.cpp"
#include "ListNode.cpp"
#include "List.cpp"
#include "ListItr.cpp"
int main()
...{
List<int> list; //定义一个单链表
cout<<list.IsEmpty()<<endl; //判断是否为空
ListItr<int> itr(list); //定义一个迭代器
for(int i=1;i<=10;i++)
itr.Insert(i); //插入10个元素
cout<<itr()<<endl; //输出当前结点的元素
cout<<itr.Remove(5)<<endl; //删除值为5的结点
cout<<list<<endl; //输出整个链表
return 0;
}
从中不难看出,绝大多数对链表的处理是通过迭代器来完成的(事实上最后的输出整个链表也是如此)。那么为何在main()中,一个迭代器对象能处理一个链表对象呢,看起来它们的“地位”似乎是一样的。请注意上述代码中的第五行:List<int> itr(list); 在定义一个迭代器 itr 时,需要将一个链表对象 list 作为参数传递给迭代器类的构造函数。迭代器类和链表类一样有一个头指针,利用链表结点的特性,在迭代器类的构造函数中,通过把链表的头指针赋给迭代器的头指针,使得它们同时指向链表的头结点,迭代器就能访问整个链表了。
以下是具体实现的代码,参考自《数据结构与算法(C++)》 2005 上海交通大学出版社 窦延平 张同珍 姜丽红 陈玉泉。(这本书我很不推荐)
链表类:
//AbsList.cpp
#define ABSLIST
#ifndef ABSLISTITR
template <class ElemType> class AbsListItr;
#endif //ABSLISTITR
template <class ElemType>
class AbsList
...{
public:
AbsList()...{}
virtual ~AbsList()...{}
virtual IsEmpty() const=0; //是否空
virtual IsFull() const=0; //是否满
virtual void MakeEmpty()=0; //清空
friend class AbsListItr<ElemType>;
private:
AbsList(const AbsList &)...{} //冻结复制另一链表的构造函数
};
链表迭代器类:
//AbsListItr.cpp
#define ABSLISTITR
#ifndef ABSLIST
template <class ElemType> class AbsList;
#endif //ABSLIST
template <class ElemType>
class AbsListItr
...{
public:
AbsListItr(const AbsList<ElemType> &L)...{}
AbsListItr(const AbsListItr&);
virtual ~AbsListItr()...{}
virtual void Insert(const ElemType &x)=0; //在当前结点后插入
virtual int Remove(const ElemType &x)=0; //删除值为x的结点
virtual int Find(const ElemType &x)=0;
virtual int IsFound(const ElemType &x) const=0;
virtual int operator+() const=0; //判断当前结点是否存在
virtual const ElemType & operator()()const=0; //取当前结点的内容
virtual void Zeroth()=0; //定位于链表的首结点之前
virtual void First()=0; //定位于链表的首结点
virtual void operator++()=0; //定位于下一结点
virtual void operator ++(int)=0;
protected:
AbsListItr()...{} //冻结无参数的构造函数
};
单链表结点类:
//ListNode.cpp
#include <iostream.h>
#ifndef LISTNODE
#define LISTNODE
#ifndef LIST
template<class ElemType> class List;
#endif //LIST
#ifndef LISTITR
template<class ElemType> class ListItr;
#endif //LISTITR
template<class ElemType>
class ListNode
...{
friend class List<ElemType>;
friend class ListItr<ElemType>;
private:
ListNode<ElemType> *Next;
ElemType Element;
public:
ListNode(const ElemType &E,ListNode<ElemType> *N=NULL):Element(E),Next(N)...{}
ListNode()...{Next=NULL;}
~ListNode()...{};
};
#endif //LISTNODE
单链表类:
//List.cpp
#define LIST
#include <iostream.h>
#ifndef ABSLIST
template<class ElemType> class AbsList;
#endif //ABSLIST
#ifndef LISTITR
template<class ElemType> class ListItr;
#endif //LISTITR
#ifndef LISTNODE
template<class ElemType> class ListNode;
#endif //LISTNODE
template<class ElemType>
class List:public AbsList<ElemType>
...{
friend class ListItr<ElemType>;
private:
ListNode<ElemType> *head;
public:
List()
...{
head=new ListNode<ElemType>;
}
~List()
...{
MakeEmpty();
delete head;
}
const List &operator=(const List &R);
int IsEmpty() const
...{
return head->Next==NULL;
}
int IsFull()const
...{
return 0;
}
void MakeEmpty();
};
template <class ElemType>
void List<ElemType>::MakeEmpty()
...{
ListNode<ElemType> *Ptr;
ListNode<ElemType> *NextNode;
for(Ptr=head->Next;Ptr!=NULL;Ptr=NextNode)
...{
NextNode=Ptr->Next;
delete Ptr;
}
head->Next=NULL;
}
template <class ElemType>
const List<ElemType> & List<ElemType>::operator=(const List<ElemType> &R)
...{
if(this==&R)
return *this;
MakeEmpty();
ListItr<ElemType> Itr(*this);
for(ListItr<ElemType> Ritr(R);+Ritr;Ritr++)
Itr.Insert(Ritr());
return *this;
}
template <class ElemType>
ostream & operator<<(ostream & Out,const List<ElemType> &L)
...{
if(L.IsEmpty())
Out<<"Empty List";
else
for(ListItr<ElemType> Itr(L);+Itr;Itr++)
Out<<Itr()<<endl;;
return Out;
}
迭代器类:
//ListItr.cpp
#define LISTITR
#ifndef ABSLISTITR
template<class ElemType> class AbsListItr;
#endif //ABSLISTITR
#ifndef LISTNODE
template<class ElemType> class ListNode;
#endif //LISTNODE
#ifndef LIST
template<class ElemType> class List;
#endif //LIST
template<class ElemType>
class ListItr:public AbsListItr<ElemType>
...{
private:
ListNode<ElemType> *const head;
ListNode<ElemType> *Current;
public:
ListItr(const List<ElemType> &L):head(L.head)
...{
Current=L.IsEmpty() ? head : head->Next;
}
~ListItr()...{}
int Find(const ElemType &x); //查找值为x的结点,成功则使其成为当前结点
int IsFound(const ElemType &x) const; //查找值为x的结点,不改变Current
void Insert(const ElemType &x);
int Remove(const ElemType &x);
int operator +() const //当前结点非空则返回True
...{
return Current && Current !=head;
}
const ElemType & operator()()const; //取当前结点的数据值
void operator ++(); //使当前结点的后继结点成为当前结点 前缀++
void operator ++(int) //将后缀++定义为前缀++
...{
operator++();
}
void Zeroth()
...{
Current=head;
}
void First();
const ListItr & operator=(const ListItr&); //赋值运算符
};
template<class ElemType>
void ListItr<ElemType>::Insert(const ElemType &x)
...{
ListNode<ElemType> *p;
p=new ListNode<ElemType>(x,Current->Next);
Current=Current->Next=p;
}
template<class ElemType>
int ListItr<ElemType>::Find(const ElemType &x)
...{
ListNode<ElemType> *Ptr=head->Next;
while(Ptr!=NULL && !(Ptr->Element==x))
Ptr=Ptr->Next;
if(Ptr==NULL)
return 0;
Current=Ptr;
return 1;
}
template<class ElemType>
int ListItr<ElemType>::IsFound(const ElemType &x) const
...{
ListNode<ElemType> *Ptr=head->Next;
while(Ptr!=NULL && !(Ptr->Element==x))
Ptr=Ptr->Next;
return Ptr!=NULL;
}
template<class ElemType>
int ListItr<ElemType>::Remove(const ElemType &x)
...{
ListNode<ElemType> *Ptr=head;
while(Ptr->Next!=NULL && !(Ptr->Next->Element==x))
Ptr=Ptr->Next;
if(Ptr->Next==NULL)
return 0;
ListNode<ElemType> *P=Ptr->Next;
Ptr->Next=Ptr->Next->Next;
delete P;
Current=head;
return 1;
}
template<class ElemType>
const ElemType & ListItr<ElemType>::operator()()const
...{
return Current->Element;
}
template<class ElemType>
void ListItr<ElemType>::operator++()
...{
Current=Current->Next;
}
template<class ElemType>
const ListItr<ElemType> &ListItr<ElemType>::operator=(const ListItr<ElemType> &R)
...{
if(this==&R)
return *this;
head=R.head;
Current=R.Current;
return *this;
}
template<class ElemType>
void ListItr<ElemType>::First()
...{
Current=head->Next;
}
细心的人肯定已经发现了,要使迭代器能够访问链表的头指针,必须将迭代器类设为链表类的友元类,这在一定程度上破坏了类的封装性。使用迭代器的初衷是未避免经常修改链表类以及链表类变的过于庞大。然而面向对象程序设计的一个基本原则是封装性和信息隐蔽。友元类虽然有助于数据共享,却违背了信息隐蔽,一般只有在使用它时能使程序精炼并能大大提高程序的效率时才使用友元。
很显然,在构建链表时使用迭代器使程序变的复杂,不利于初学者把精力放在数据结构本身上。同时以破坏封装性为代价,在小规模程序中并没有提高程序的效率(反而是降低了)。因此我建议初学者在学习数据结构时不要使用迭代器。
可以通过此链接下载本程序:http://cid-24fba8dfcc188fae.skydrive.live.com/self.aspx/Public/ListItr.rar
相关文章推荐
- Python 使用由单链表构建的数组实现有边际优先队列 (基于class, 包含迭代器)
- c链表构建学生档案数据库
- 链表操作造成的指针失效问题(类比STL中的迭代器失效)
- 二叉树的二叉链表存储结构构建以及先序遍历
- [C++]List with iterator(链表的迭代器实现)
- c/c++:一个带迭代器的链表模板 iterator
- 设计模式之--迭代器模式(自定义迭代器与STL::find()配合查找链表元素)
- C++通用链表构建(二)
- 用数组 和 链表 构建栈
- Java(7-2 迭代器和链表详细说明)
- STL里的list是双链表 有双向迭代器,不能随机访问
- 简单实现c++数组,链表及其迭代器
- 构建动态链表
- 链表初尝试-链表的构建与输出-指针
- JAVA实现具有迭代器的线性表(单链表)
- 指针理解错误之构建链表操作
- 构建高性能服务(一)ConcurrentSkipListMap和链表构建高性能Java Memcached
- C实现头插法和尾插法来构建链表
- 链表之构建
- JavaScript根据数组构建链表