一、目标
实现一个链表,其中的元素类型可以不同。
二、思路
【思路一】
在结点中用共用体保存数据,用void*指针指向下一个结点,并且在结点中记录本结点的数据类型。
0000 enum Type {INT, CHAR, STRING};
0001 struct Node{
0002 Type NodeType;
0003 union {
0004 int intData;
0005 char charData;
0006 string strData;
0007 }value;
0008 void *next;
0009 };
链表的每一个元素其实还都是一样的
【思路二】
设计一个抽象结点类,不同数据类型的结点来继承它。用基类的指针可以指向每一个派生类。
【思路三】
上面两种思路都要求数据类型已知,难以添加新的类型。于是把【思路二】略修改一下,用模板写了派生类。
三、代码
0000 #ifndef HETERLIST_H
0001 #define HETERLIST_H
0002 #include <iostream>
0003 #include <list>
0004
0005 struct Pointer{
0006 //用于遍历时打印结点数据
0007 virtual std::ostream& printData(std::ostream&)=0;
0008 //用于搜索时判断两结点是否相等
0009 virtual bool operator ==(Pointer*)=0;
0010 };
0011
0012 template<typename T>
0013 class Node : public Pointer {
0014 T _data;
0015 public:
0016 Node():_data(0){}
0017 Node(T data):_data(data){}
0018 virtual std::ostream& printData(std::ostream& out)
0019 {out << _data;return out;}
0020 virtual bool operator == (Pointer* p)
0021 {
0022 if (Node<T>* pp=dynamic_cast<Node<T>*>(p))
0023 return _data==pp->getData();
0024 else
0025 return false;
0026 }
0027 const T getData() const{return _data;}
0028 void setData(T d){data=d;}
0029 virtual ~Node(){};
0030 };
0031
0032 std::ostream& operator << (std::ostream& out, Pointer* p)
0033 {
0034 return p->printData(out);
0035 }
0036
0037
0038 typedef std::list<Pointer*> HeterList;
0039 typedef std::list<Pointer*>::iterator HLI;
0040
0041 #endif // HETERLIST_H
0000 #include <iostream>
0001 #include <string>
0002 #include <cstdlib>
0003 #include "HeterList.h"
0004 using namespace std;
0005
0006 //自定义一个简单的类,用于测试本异质链表是否可以插入自定义类
0007 //从异质链表的定义可见,要求自定义类重载operator <<和==
0008 class classNode{
0009 string _str;
0010 public:
0011 classNode(string s=0):_str(s){}
0012 string getData()const {return _str;}
0013 ostream& printData(ostream& out){out<< _str;return out;}
0014 bool operator == (classNode n){return _str==n.getData();}
0015 };
0016 //避免用友元,保持类的封装性
0017 ostream& operator << (ostream& out, classNode* n)
0018 {
0019 return n->printData(out);
0020 }
0021
0022 int main()
0023 {
0024 //定义一个异质链表testList
0025 HeterList testList;
0026 //为了测试,定义了三种不同“质”的结点。实际上由于用了template,
0027 //本异质链表可以插入任意类型的结点。但有个前提条件:如果是类
0028 //的话,这个类要求重载operator <<和==
0029 Node<int>* intNode;
0030 Node<char>* charNode;
0031 Node<classNode*>* userNode;
0032
0033 classNode* tempClassNode;
0034
0035 //插入int型元素
0036 for (int i = 0; i< 3; ++i){
0037 intNode = new Node<int>(i);
0038 testList.push_back(intNode);
0039 }
0040 //插入char型元素
0041 for (char c = 'a'; c< 'c'+1; ++c){
0042 charNode = new Node<char>(c);
0043 testList.push_back(charNode);
0044 }
0045
0046 //插入自定义类
0047 for (int i = 0; i< 3; ++i){
0048 string s = "My class ";
0049 s += char(i+48); //'0'的ACII码是48
0050 tempClassNode=new classNode(s);
0051 userNode = new Node<classNode*>(tempClassNode);
0052 testList.push_back(userNode);
0053 }
0054
0055 cout << "遍历链表:" <<endl;
0056 for (HLI i = testList.begin(); i!=testList.end(); ++i){
0057 cout << *i << endl;
0058 }
0059 //销毁异质链表。注意:如果链表元素是自定义类指针,先要销毁该指针
0060 //所指向的对象
0061 cout << "销毁链表:" <<endl;
0062 int j=0;
0063 for (HLI i = testList.begin(); i!=testList.end(); ++i,++j){
0064 cout << "Deleting Node "
0065 << j <<": " << *i<< " ..." << endl;
0066
0067 if (Node<classNode*>* p
0068 = dynamic_cast<Node<classNode*>*>(*i))
0069 {
0070 cout << "Deleting "
0071 << p->getData() << " ..." << endl;
0072 delete p->getData();
0073 }
0074 delete *i;
0075 }
0076 }
0077
因篇幅问题不能全部显示,请点此查看更多更全内容