线性表链接实现--双循环链表

                    在实现时没有引入两个辅助节点,所以实现时需要考虑特殊情况,比如头和尾插入删除操作时,需要改变指向头和尾的指针。在做迭代器的时候还有麻烦,遍历链表时需要借助量表的长度,不然不能标识结束,我想到的办法是在迭代器中做一些记录工作,比如当前的下标和整个链表的长度。有解决办法的希望指教。

                   

#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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值