1. 程式人生 > >C++ STL之List實現

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;
}

最後

   如有錯誤,歡迎大家批評交流!