異質鏈表,是一種每一個節點能夠存儲不一樣類型對象的鏈表。
C++實現異質鏈表,的關鍵技術是模版元編程和多態性,很少說,直接看代碼。node
代碼主要分爲兩部分:AnyElement.h 和 AnyList.hios
AnyElement.h
包含AnyElment、ElementBase、Element 三個類;
ElementBase和Element嵌套在AnyElment類之中;
Element類繼承ElementBase類;
Element類是一個模版類;
在AnyElement中經過ElementBase類的指針來存儲不一樣類型的Element類。編程
#ifndef ANYELEMENT_H #define ANYELEMENT_H #include<stdexcept> /** * The class that can store any type of value implement by polymorphism. */ class AnyElement{ class ElementBase{//virtual class for inherit public: virtual ~ElementBase(){ }//virtual destructor }; template<typename T> class Element : public ElementBase{ public: T value; Element(const T& _value) :value(_value){ } }; ElementBase* pelement; //a base class pointer public: AnyElement() //default constructor :pelement(nullptr){ } template<typename T> AnyElement(const T& _value) //constructor :pelement(new Element<T>(_value)){ } ~AnyElement(){ //destructor delete pelement; } template<typename T> T& get(){ //get the Element's value by pelement auto pderived = dynamic_cast<Element<T>*>(pelement); if(nullptr == pderived){ throw std::invalid_argument("The type to dynamic_cast is wrong"); } return pderived->value; } }; #endif //ANYELEMENT_H
AnyList.h
包含了鏈表的節點類和主體類,其內容與通常的鏈表差異不大;
其主要函數列表以下:
基本功能
AnyList();
~AnyList();
iterator begin();
iterator end();
bool isempty();
void clear();
void reverse();
void merge(AnyList& anotherList);函數
(如下爲模版函數,爲了簡潔,template<typename T>省略不寫)
功能:在不一樣位置插入節點
void push_back(const T& _data,Type _type);
void push_front(const T& _data,Type _type);
void insert(const T& _data,ListNode* _prev,Type _type);
功能:得到不一樣位置的對象
T& peek_back();
T& peek_front();
T& get(ListNode* position);
功能:刪除不一樣位置的節點
bool pop_back();
bool pop_front();
bool drop(iterator position);測試
#ifndef ANYLIST_ANYLIST_H #define ANYLIST_ANYLIST_H #include <iostream> #include "AnyElement.h" /********************************************************** * Before using this list you should add all types that you * * need to use to the enum Type. * ***********************************************************/ typedef enum TYPE{ INT = 0, FLOAT = 1, DOUBLE = 2, STRING = 3, TEST = 4 } Type; /*******NOTE:Don't change code after the hr*****************/ /** The Node of the LinkList */ struct ListNode{ Type type; AnyElement data; ListNode *prev; ListNode *next; template<typename T> ListNode(const T& _data,ListNode* _prev,ListNode* _next,const Type& _type) :data(_data),prev(_prev),next(_next),type(_type){ } }; /** The AnyList class */ class AnyList{ ListNode* head; ListNode* tail; public: using iterator = ListNode*; AnyList()//constructor :head(nullptr),tail(nullptr){ } ~AnyList(){//destructor while(head){ ListNode* temp = head; head = head->next; delete head; } } iterator begin(){//get the head pointer return head; } iterator end(){//get the pointer after tail return nullptr; } bool isempty(){//is empty return nullptr == head; } void clear(){//destroy all content while(head){ ListNode* temp = head; head = head->next; delete head; } head = tail = nullptr; } void clear_for_merge(){//just foe merge head = tail = nullptr; } void reverse(){//reverse the order of the node if(head==tail) return ; ListNode *pres = tail, *oriTail = tail, *ptem = tail->prev; tail = head; head = oriTail; pres->prev = nullptr; while(nullptr != ptem){ pres->next = ptem; ptem = ptem->prev; pres->next->prev = ptem; pres = pres->next; } pres->next = nullptr; } void merge(AnyList& anotherList){//merge anotherList to this list if(anotherList.head==nullptr) return ; tail->next = anotherList.head; anotherList.head->prev = tail; tail = anotherList.tail; anotherList.clear_for_merge(); } template<typename T> void push_back(const T& _data,Type _type){//insert after tail ListNode* newNode = new ListNode(_data,tail,nullptr,_type); if(nullptr == head){ head = newNode; tail = newNode; return ; } tail->next = newNode; tail = newNode; } template<typename T> void push_front(const T& _data,Type _type){//insert before head ListNode* newNode = new ListNode(_data,nullptr,head,_type); if(nullptr == tail){ head = newNode; tail = newNode; return ; } head->prev = newNode; head = newNode; } template<typename T>//insert after _prev void insert(const T& _data,ListNode* _prev,Type _type){ if(nullptr == _prev){ std::cerr << "The prev location doesn't exist." << std::endl; return ; } ListNode* newNode = new ListNode(_data,_prev,_prev->next,_type); _prev->next = newNode; if(newNode->next) newNode->next->prev = newNode; if(tail == _prev) tail = newNode; } //before execute these function you must execute isempty() template<typename T> T& get(ListNode* position){//get data in position return position->data.get<T>(); } template<typename T> T& peek_back(){//get data in tail return get<T>(tail); } template<typename T> T& peek_front(){//get data in head return get<T>(head); } bool drop(iterator position){//delete node in position if(isempty()){ std::cerr<<"Error in drop: list is empty!"<<std::endl; return false; } ListNode* ptem = nullptr; if(head == tail){ ptem = head; head = tail = nullptr; delete ptem; }else if(position == head){ ptem = head; head = head->next; head->prev = nullptr; delete ptem; }else if(position == tail){ ptem = tail; tail = tail->prev; tail->next = nullptr; delete ptem; }else{ position->prev->next = position->next; position->next->prev = position->prev; delete position; } return true; } bool pop_back(){//drop tail return drop(tail); } bool pop_front(){//drop head return drop(head); } }; #endif //ANYLIST_ANYLIST_H
測試程序this
#include<iostream> #include"AnyList.h" using namespace std; class Test{// for test public: int real; int virt; Test(int _real,int _virt) :real(_real),virt(_virt){} friend ostream& operator<<(ostream& out,const Test& test); }; ostream& operator<<(ostream& cout,const Test& test){ cout<<test.real<<"+"<<test.virt<<"i"; return cout; } void print(AnyList &list){ if(list.isempty()) return; for(auto i = list.begin();i!=list.end();i=i->next){ switch(i->type){ case INT: { auto data = list.get<int>(i); cout<<data<<endl; break; } case DOUBLE: { auto data = list.get<double>(i); cout<<data<<endl; break; } case STRING: { auto data = list.get<string>(i); cout<<data<<endl; break; } case TEST: { auto data = list.get<Test>(i); cout<<data<<endl; break; } default: { cerr<<"Some error in insert!"<<endl; break; } } } } int main(int argc, char const *argv[]) { AnyList list,list2; Test test(1,5); list.push_back(10,INT); list.push_front(string("AnyList Test Data"),STRING); list.push_back(1.5,DOUBLE); list.push_back(test,TEST); list.push_back(string("hello world1"),STRING); list.push_front(123456789,INT); list2.push_back(1,INT); list2.push_back(2,INT); list2.push_back(3,INT); cout<<"------>original list:"<<endl; print(list); cout<<"------>reverse list:"<<endl; list.reverse(); print(list); cout<<"------>mergte list:"<<endl; list.merge(list2); list2.clear(); print(list); cout<<"------>delete list:"<<endl; list.pop_back(); list.pop_front(); print(list); return 0; }