双链表

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;
}
原文地址:https://www.cnblogs.com/LC32/p/13452664.html