您的位置:首页 > 其它

用迭代器构建的单链表

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: