線性表連接實現--雙循環鏈表

                    在實現時沒有引入兩個輔助節點,因此實現時須要考慮特殊狀況,好比頭和尾插入刪除操做時,須要改變指向頭和尾的指針。在作迭代器的時候還有麻煩,遍歷鏈表時須要藉助量表的長度,否則不能標識結束,我想到的辦法是在迭代器中作一些記錄工做,好比當前的下標和整個鏈表的長度。有解決辦法的但願指教。node

                   

#ifndef LINKLIST_H
#define LINKLIST_H
#include "list.hpp"

template <typename T>
struct node {
    T d;
    node *pre, *next;
    node(const T& _d, node *_pre = NULL, node *_next = NULL):
        d(_d),
        pre(_pre),
        next(_next) {

    }
};


template <typename T>
class LinkList : public List<T>
{
public:
    /**
     * @brief The Iterator class 雙循環鏈表設計時沒有頭和尾節點,因此在設計迭代器時不方便,好比遍歷鏈表必須藉助鏈表的長度
     */
    class Iterator
    {
        friend std::ostream& operator << (std::ostream &os, const Iterator &obj) {
            os << obj.p->d;
            return os;
        }
    public:
        Iterator(node<T> *_p):p(_p){}
        ~Iterator(){}
        Iterator(const Iterator& obj):p(obj.p){}
        Iterator& operator = (const Iterator& obj) {
            p = obj.p;
            return *this;
        }

        Iterator& operator ++() {
            p = p->next;
            return *this;
        }
        Iterator operator ++(int) {
            Iterator t(p);
            p = p->next;
            return  t;
        }
        Iterator& operator -- (){
            p = p->pre;
            return *this;
        }
        Iterator operator -- (int) {
            Iterator t(p);
            p = p->pre;
            return  t;
        }
        T operator * () {
            return p->d;
        }
        T* operator -> () {
            return &p->d;
        }

        bool operator == (const Iterator &ite) {
            return p == ite.p;
        }

        bool operator != (const Iterator &ite) {
            return p != ite.p;
        }
    private:
        node<T> *p;
    };
    LinkList():head(NULL),tail(NULL),size(0) {}
    ~LinkList();
    void clear();
    int length() const;
    /**
     * @brief insert 插入到鏈表的指定位置 插入i的下個位置
     * @param i 下標 從0開始
     * @param t
     */
    void insert(int i, const T &t);
    int search(const T &t) const;
    T visit(int i) const;
    void traverse(std::ostream &os = std::cout) const;
    void remove(int i);
    void add(const T& o);
    void push_front(const T& o);
    void push_tail(const T& o);
    T pop_front();
    T pop_tail();
    Iterator begin() const {
        return Iterator(head);
    }
private:
    node<T> *head, *tail;
    int size;
    node<T>* local(int i) const;
};

template <typename T>
LinkList<T>::~LinkList()
{
    clear();
}

template <typename T>
/**
 * @brief LinkList<T>::add 在雙循環鏈表的tail添加節點
 * @param o
 */
void LinkList<T>::add(const T &o)
{
    node<T> *p = NULL;
    if (size == 0) {
        p = new node<T>(o);
        head = tail = p;
        head->pre = tail;
        tail->next = head;
    } else {
        p = new node<T>(o,tail,head);
        head->pre = p;
        tail->next = p;
        tail = p;
    }
    ++size;
}


template <typename T>
node<T> *LinkList<T>::local(int i) const
{
    if (i < 0 ||i > size - 1) throw BadValue();
    node<T> *p = head;
    for (int j = 0;j < i;++j) {
        p = p->next;
    }
    return p;
}


template <typename T>
/**
 * @brief LinkList<T>::clear 只有一個節點
 */
void LinkList<T>::clear()
{
    node<T> *p = head;
    while(size--) {
        head = head->next;
        delete p;
        p = head;
    }
    head = tail = NULL;
    size = 0;
}

template <typename T>
/**
 * @brief LinkList<T>::insert 插在i的後面
 * @param i
 * @param t
 */
void LinkList<T>::insert(int i, const T &t)
{
    if ((size == 0 && i == 0) || size-1 == i) {//過濾掉空鏈表插入和尾部插入
        add(t);
    } else {
        node<T> *p = local(i);//i節點
        node<T> *n = p->next;//下個節點
        node<T> *d = new node<T>(t,p,n);
        p->next = d;
        n->pre = d;
        ++size;
    }

}

template <typename T>
int LinkList<T>::length() const
{
    return size;
}

template <typename T>
int LinkList<T>::search(const T &t) const
{
    int re = -1;
    node<T> *p = head;
    for (int i = 0;i < size;++i) {
        if (p->d == t) {
            re = i;
            break;
        }
        p = p->next;
    }
    return re;
}

template <typename T>
T LinkList<T>::visit(int i) const
{
    return local(i)->d;
}
template <typename T>
void LinkList<T>::remove(int i)
{
    node<T> *p = local(i);
    p->pre->next = p->next;
    p->next->pre = p->pre;
    --size;
    if (i == 0) {
        head = p->next;
        tail->next = head;
    }
    if (i == size-1) {
        tail = p->pre;
        head->pre = tail;
    }
    delete p;
}

template <typename T>
void LinkList<T>::traverse(std::ostream &os) const
{
    node<T> *p = head;
    for (int i = 0;i < size;++i) {
        os << p->d << "    ";
        p = p->next;
    }

}

template <typename T>
/**
 * @brief LinkList<T>::push_front 插入頭部
 * @param o
 */
void LinkList<T>::push_front(const T &o)
{
    node<T> *p = new node<T>(o,tail,head);
    p->next =head;
    p->pre = tail;
    head = p;
    ++size;

}
template <typename T>
void LinkList<T>::push_tail(const T &o)
{
    add(o);
}

template <typename T>
T LinkList<T>::pop_front()
{
    T t = local(0)->d;
    remove(0);
    return t;
}
template <typename T>
T LinkList<T>::pop_tail()
{
    T t = local(size-1)->d;
    remove(size-1);
    return t;
}


#endif
相關文章
相關標籤/搜索