双链表
1.把双链表这种数据结构的更高一级别抽象(线性表)单独写成一个抽象类,然后用于双链表类的继承,这种写法可以规范双链表应该有的接口/操作
2.把节点定义为类内的结构体而不是单独的代码显得更加简洁。
3.在双链表的插入/删除/查找操作中都要找到指向第i个节点的指针,把这个操作统一定义为一个私有的辅助函数move(),可以简化代码
#include <iostream> using namespace std; // 线性表:顺序表和链表共同的抽象类 template<typename elemType> class list{ public: virtual void clear() = 0; // 删除线性表中的所有数据元素 virtual int length() const = 0; // 求线性表的长度 virtual void insert(int i, const elemType & x) = 0; // 在第i个位置插入一个元素 virtual void remove(int i) = 0; // 删除第i个位置的元素 virtual int search(const elemType & x) const = 0; // 搜索某个元素x在线性表中是否出现 virtual elemType visit(int i) const = 0; // 返回线性表中第i个数据元素的值 virtual void traverse() const = 0; // 按序访问线性表的每一数据元素 virtual ~list(){}; }; // 双链表 template<typename elemType> class dLinkList:public list<elemType>{ private: struct node{ elemType data; node *prev, *next; node(const elemType & x, node* p = NULL, node* n = NULL) {data = x; prev = p; next = n;} node():next(NULL), prev(NULL){} ~node(){} }; node *head, *tail; int currentLength; node* move(int i) const; class NoSuchNodeError{}; public: dLinkList(); ~dLinkList(){clear(); delete head; delete tail;} void clear(); int length() const{return currentLength;} void insert(int i, const elemType & x); void remove(int i); int search(const elemType & x) const; elemType visit(int i) const; void traverse() const; }; template<typename elemType> typename dLinkList<elemType>::node* dLinkList<elemType>::move(int i) const{ node* p = head; while(i-- >= 0) p = p->next; return p; } template<typename elemType> dLinkList<elemType>::dLinkList(){ head = new node; tail = new node; head->next = tail; tail->prev = head; currentLength = 0; } template<typename elemType> void dLinkList<elemType>::clear(){ node* p = head->next; node* q; head->next = tail; tail->prev = head; while(p != tail){ q = p->next; delete p; p = q; } currentLength = 0; } template<typename elemType> void dLinkList<elemType>::insert(int i, const elemType & x){ if(i > currentLength || i < 0) throw NoSuchNodeError(); node* pos = move(i); node* tmp = new node(x, pos->prev, pos); pos->prev->next = tmp; pos->prev = tmp; ++currentLength; } template<typename elemType> void dLinkList<elemType>::remove(int i){ if(i >= currentLength || i < 0) throw NoSuchNodeError(); node* pos = move(i); pos->prev->next = pos->next; pos->next->prev = pos->prev; delete pos; --currentLength; } template<typename elemType> int dLinkList<elemType>::search(const elemType & x) const{ node* p = head->next; int i; for(i = 0; p != tail && p->data != x; ++i) p = p->next; if(p == tail) return -1; else return i; } template<typename elemType> elemType dLinkList<elemType>::visit(int i) const{ if(i >= currentLength || i < 0) throw NoSuchNodeError(); return move(i)->data; } template<typename elemType> void dLinkList<elemType>::traverse() const{ node* p = head->next; while(p != tail){ cout << p->data << " "; p = p->next; } cout << endl; }