C++ STL之List实现

概述

    List是STL中常用的容器之一,List将元素按顺序储存到链表中,在快速删除和快速插入方面比vector高出许多。STL中的list是一双向链表,具有指向前一节点和后一节点的指针。那么我们开始写一个属于自己的List吧。

list的节点

    list的节点应由指向前一节点的指针,指向后一节点的指针一节储存的元素构成。那么我给出节点的定义

template <typename Object> struct Node {
    Object object;
    Node<Object> *previous;//指向前一节点
    Node<Object> *next;//指向后一节点
    Node(const Object&obj) :object(obj), next(NULL),previous(NULL) {}
    Node():next(NULL),previous(NULL){}
};

迭代器的实现

    迭代器类似于指针类型,它也提供了对对象的间接访问。我们可以通过迭代器的遍历来遍历整个链表,也可通过操作迭代器来删除或插入元素。

    STL中迭代器有两种:iterator和const_iterator。前一种允许通过迭代器来改变元素的值,后一种则不允许通过迭代器来改变元素值。

    我们可以将const_iterator作为父类,iterator作为基类。

template <typename Object> class const_iterator {
protected:
    Node<Object>* current;
    Object& retrieve()const { return current->data; }
public:
    const_iterator() :current(NULL) {}
    const Object&operator*()const;
    const_iterator &operator++(int);
    const_iterator&operator++();
    bool operator==(const const_iterator&);
    bool operator!=(const const_iterator&);
    friend class List<Object>;
};
template <typename Object> const Object& const_iterator<Object>::operator*() const {
    return current->object;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++(int) {
    const_iterator old = *this;
    ++(*this);
    return old;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++() {
    current = current->next;
    return *this;
}
template <typename Object>bool const_iterator<Object>::operator==(const const_iterator &rhs) {
    return current == rhs.current ? true : false;
}
template <typename Object>bool const_iterator<Object>::operator!=(const const_iterator &rhs) {
    return !(this->current == rhs.current);
}

    通过重载++,==等运算符,使我们的迭代器实现自增以及比较是否相等的功能。

    下面是iterator的代码:

template <typename Object> class iterator :public const_iterator<Object> {
public:
    iterator() {}
    Object&operator*() { return const_iterator<Object>::current->object; }
    const Object&operator*()const { return const_iterator<Object>::operator*(); }
    iterator&operator++() {
        const_iterator<Object>::current = const_iterator<Object>::current->next;
        return *this;
    }
    iterator&operator++(int) {
        iterator old = *this;
        ++(*this);
        return old;
    }
    friend class List<Object>;
};

List的实现

    前面说到list用双向链表实现,我们可以在list中设置一个没有储存元素的头结点和尾节点,这样可以使插入删除等操作变得相同,即无论头结点是否为空,都执行相投操作。以及在向后插入元素时,由于记住了尾节点,只需要O(1)的复杂度。我们仅仅只用了两个空的节点,就极大的提高了效率。

    在编写代码的时候值得注意的是,防止野指针的出现,以及别搞错了指针的指向。

template <typename Object> class List {
private:
    Node<Object> *head;
    Node<Object> *tail;
    int theSize;
public:
    typedef iterator<Object> iterator;
    typedef const_iterator<Object> const_iterator;
    List();
    ~List();
    List(const List<Object>&);
    List(unsigned initSize);
    void push_back(const Object&);
    void push_front(const Object&);
    void pop_front();
    void pop_back();
    bool empty();
    void clear();
    void resize(unsigned);
    const Object& front();
    const Object& back();
    int size()const;
    void insert(iterator, const Object&);
    void remove(const Object&);
    const List<Object>&operator=(const List<Object>&);
    iterator begin() {
        iterator it;
        it.current = head->next;
        return it;
    }
    iterator end() {
        iterator it;
        it.current = tail;
        return it;
    }
    const_iterator begin()const{
        const_iterator it;
        it.current=head->next;
        return it;
    }
    const_iterator end()const{
        const_iterator it;
        it.current=tail;
        return it;
    }
    iterator erase(iterator it){
        if(it!=end()&&!empty()){
        Node<Object>*tmp=it.current;
        Node<Object>*p=tmp;
        tmp->previous->next=tmp->next;
        tmp=tmp->next;
        delete p;
        iterator to;
        to.current=tmp;
        --theSize;
        return to;
        }
    }
};
template <typename Object> List<Object>::~List() {
    clear();
    delete head;
    delete tail;
}
template <typename Object> List<Object>::List() :head(new Node<Object>()), theSize(0),tail(new Node<Object>()) {
    tail->previous=head;
    head->next=tail;
}
template <typename Object> List<Object>::List(unsigned initSize) : head(new Node<Object>()),theSize(initSize),tail(new Node<Object>()) {
    tail->previous=head;
    head->next=tail;
    for (int i = 0; i < theSize; i++) {
        Node<Object>*tmp = new Node<Object>();
        tail->previous->next=tmp;
        tmp->previous=tail->previous;
        tail->previous=tmp;
        tmp->next=tail;
    }
}
template <typename Object> List<Object>::List(const List<Object> &rhs):head(new Node<Object>()),tail(new Node<Object>()),theSize(0) {
    tail->previous=head;
    head->next=tail;
    for(const_iterator it=rhs.begin();it!=rhs.end();++it)
        push_back(*it);
}
template <typename Object> const List<Object>& List<Object>::operator=(const List<Object> &rhs) {
    if(this==&rhs)return *this;
    clear();
    for(const_iterator it=rhs.begin();it!=rhs.end();++it)
        push_back(*it);
    return *this;
}
template <typename Object> void List<Object>::push_back(const Object &rhs) {
    Node<Object>*tmp=new Node<Object>(rhs);
    tail->previous->next=tmp;
    tmp->previous=tail->previous;
    tail->previous=tmp;
    tmp->next=tail;
    ++theSize;
}
template <typename Object> void List<Object>::pop_back() {
    if(empty())return;
    else{
        Node<Object>*tmp=tail->previous;
        tmp->previous->next=tail;
        tail->previous=tmp->previous;
        delete tmp;
        --theSize;
    }
}
template <typename Object> void List<Object>::push_front(const Object &obj) {
    Node<Object>*tmp = new Node<Object>(obj);
    tmp->previous=head;
    head->next->previous=tmp;
    tmp->next = head->next;
    head->next = tmp;
    ++theSize;
}
template <typename Object> void List<Object>::pop_front() {
    if (empty()) return;
    else {
        Node<Object>*tmp = head->next;
        head->next = tmp->next;
        delete tmp;
        --theSize;
    }
}
template <typename Object> int List<Object>::size() const {
    return theSize;
}
template <typename Object> bool List<Object>::empty() {
    return theSize == 0 ? true : false;
}
template <typename Object> void List<Object>::clear() {
    while (!empty()){
        pop_back();
    }
}
template <typename Object> const Object& List<Object>::front() {
    if (!empty())
        return head->next->object;
}
template <typename Object> const Object& List<Object>::back() {
    if(!empty()){
        return tail->previous->object;
    }
}
template <typename Object> void List<Object>::remove(const Object &obj) {
    if(empty())return;
    else{
        Node<Object>*tmp=head->next;
        while(tmp!=tail){
            if(tmp->object==obj){
                Node<Object>*p=tmp;
                tmp->previous->next=tmp->next;
                tmp->next->previous=p->previous;
                tmp=tmp->next;
                std::cout<<"remove()"<<p->object<<std::endl;
                delete p;
                p=NULL;
                --theSize;
            }
            else
                tmp=tmp->next;

        }
    }
}
template <typename Object> void List<Object>::resize(unsigned newSize) {
    if(newSize==theSize)return;
    else if(newSize<theSize){
        int num=theSize-newSize;
        for(int i=0;i<num;i++) {
            std::cout<<"pop"<<back()<<" ";
            pop_back();
        }
    }
    else{
        int num=newSize-theSize;
        for(int i=0;i<num;i++)
            push_back(Object());
    }
}
template <typename Object> const Object& const_iterator<Object>::operator*() const {
    return current->object;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++(int) {
    const_iterator old = *this;
    ++(*this);
    return old;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++() {
    current = current->next;
    return *this;
}
template <typename Object>bool const_iterator<Object>::operator==(const const_iterator &rhs) {
    return current == rhs.current ? true : false;
}
template <typename Object>bool const_iterator<Object>::operator!=(const const_iterator &rhs) {
    return !(this->current == rhs.current);
}
template <typename Object>void List<Object>::insert(iterator it, const Object &obj) {
    Node<Object> *tmp = it.current;
    Node<Object>* p = new Node<Object>(obj);
    tmp->previous->next=p;
    p->next = tmp;
    p->previous=tmp->previous;
    tmp->previous=p;
    ++theSize;
}

最后

   如有错误,欢迎大家批评交流!

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STL(Standard Template Library)是C++中的一个标准库,其中包含了许多常用的数据结构和算法。其中,list是一种常用的数据结构,它是一个双向链表,可以实现快速的插入和删除操作。 下面是C++STL list的简单实现: ```cpp template <typename T> class List { private: struct Node { T data; Node* prev; Node* next; Node(const T& d = T(), Node* p = nullptr, Node* n = nullptr) : data(d), prev(p), next(n) {} }; Node* head; Node* tail; int size; public: List() : head(nullptr), tail(nullptr), size(0) {} List(const List& other) : head(nullptr), tail(nullptr), size(0) { for (const auto& item : other) { push_back(item); } } ~List() { clear(); } List& operator=(const List& other) { if (this != &other) { List tmp(other); swap(tmp); } return *this; } void push_back(const T& item) { Node* new_node = new Node(item, tail, nullptr); if (tail) { tail->next = new_node; } else { head = new_node; } tail = new_node; ++size; } void push_front(const T& item) { Node* new_node = new Node(item, nullptr, head); if (head) { head->prev = new_node; } else { tail = new_node; } head = new_node; ++size; } void pop_back() { if (tail) { Node* tmp = tail; tail = tail->prev; if (tail) { tail->next = nullptr; } else { head = nullptr; } delete tmp; --size; } } void pop_front() { if (head) { Node* tmp = head; head = head->next; if (head) { head->prev = nullptr; } else { tail = nullptr; } delete tmp; --size; } } T& front() { return head->data; } T& back() { return tail->data; } bool empty() const { return size == 0; } int size() const { return size; } void clear() { while (!empty()) { pop_back(); } } class iterator { private: Node* ptr; public: iterator(Node* p = nullptr) : ptr(p) {} iterator(const iterator& other) : ptr(other.ptr) {} iterator& operator++() { ptr = ptr->next; return *this; } iterator operator++(int) { iterator tmp(*this); ptr = ptr->next; return tmp; } iterator& operator--() { ptr = ptr->prev; return *this; } iterator operator--(int) { iterator tmp(*this); ptr = ptr->prev; return tmp; } T& operator*() const { return ptr->data; } T* operator->() const { return &(ptr->data); } bool operator==(const iterator& other) const { return ptr == other.ptr; } bool operator!=(const iterator& other) const { return ptr != other.ptr; } }; iterator begin() const { return iterator(head); } iterator end() const { return iterator(nullptr); } iterator rbegin() const { return iterator(tail); } iterator rend() const { return iterator(nullptr); } void swap(List& other) { std::swap(head, other.head); std::swap(tail, other.tail); std::swap(size, other.size); } }; ``` 上述代码中,List类中定义了一个私有结构体Node,它表示双向链表中的每个节点。Node中包含了数据成员data、指向前一个节点的指针prev和指向后一个节点的指针next。List类中还包含了头指针head、尾指针tail和大小size等数据成员。 List类提供了许多操作,包括push_back、push_front、pop_back、pop_front、front、back、empty、size、clear等。其中,push_back和push_front分别表示在双向链表的末尾和开头插入一个元素,pop_back和pop_front分别表示删除双向链表的末尾和开头的元素,front和back分别表示获取双向链表的第一个和最后一个元素,empty表示判断双向链表是否为空,size表示获取双向链表中元素的个数,clear表示清空双向链表中的所有元素。 List类还定义了一个迭代器iterator,它可以用于遍历双向链表中的所有元素。迭代器中包含了一个指向Node的指针ptr,它可以指向双向链表中的任意一个节点。迭代器提供了许多操作,包括++、--、*、->、==、!=等。其中,++和--分别表示迭代器向前和向后移动一个位置,*表示获取迭代器所指向节点的数据成员data,->表示获取迭代器所指向节点的数据成员data的指针,==和!=分别表示判断两个迭代器是否相等和不相等。 List类中还提供了一些其他操作,比如拷贝构造函数、析构函数、赋值运算符、begin、end、rbegin、rend和swap等。其中,拷贝构造函数用于复制另一个List对象,析构函数用于释放所有节点的内存,赋值运算符用于将一个List对象赋值给另一个List对象,begin和end分别返回指向双向链表中第一个元素和最后一个元素的迭代器,rbegin和rend分别返回指向双向链表中最后一个元素和第一个元素的迭代器,swap用于交换两个List对象中的所有数据成员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值