單向鏈表-slist

單向鏈表-slist

博主所分享的這個單向鏈表slist,是依據侯捷老師的《STL源碼解析》中slist一節的slist,因爲博主在跑書上slist上的例子時,發現#include<slist> 報錯,編譯器並沒有提供slist這個庫,所以自己就依照書上的代碼,照葫蘆畫瓢自己實現了一個簡單的slist。這裏slist主要由節點、迭代器以及slist本身的數據結構組成。


節點的定義

節點的定義如下,定義在nodeStruct.h的頭文件中:

//nodeStruct.h
template<class T>
struct nodeStruct{
    T data;
    nodeStruct* next;
};

slist迭代器的定義

迭代器的定義如下,定義在slist_iterator.h的頭文件中:

//slist_iterator.h
#include "nodeStruct.h"
template<class T,class Ref,class Ptr>
class iterator_{
    typedef iterator_<T, T&, T*> iterator;
    typedef iterator_<T, const T&, const T*> const_iterator;
    typedef iterator_<T, Ref, Ptr> self;

    typedef T value_type;
    typedef Ref reference;
    typedef Ptr pointer;
    typedef nodeStruct<T> node;
public:
    node* nnn;//定義一個node節點
public:
    iterator_(node* x) :nnn(x){}//構造函數
    iterator_() : nnn(0){}//構造函數
    iterator_(const iterator& iter) :nnn(iter.nnn){}//拷貝構造函數
    //重載等號運算符
    self& operator=(const iterator& iter)
    {
        nnn = iter.nnn;
        return *this;
    }
    //判斷兩個迭代器是否相等
    bool operator==(const iterator& iter)
    {
        return nnn == iter.nnn;
    }
    //判斷兩個迭代器是否不相等
    bool operator!=(const iterator& iter)
    {
        return nnn != iter.nnn;
    }
    //迭代器自增
    self& operator++()
    {
        nnn = nnn->next;
        return *this;
    }
    //迭代器自增
    self operator++(int)
    {
        self tmp = *this;
        ++(*this);
        return tmp;
    }
    //重載+=運算符
    self operator+=(int n)
    {
        while (n-- > 0)
        {
            if (nnn == 0)
                return iterator(0);
            nnn = nnn->next
        }
        return *this;
    }
    //重載*運算符,獲取數據
    reference operator*()
    {
        return nnn->data;
    }
    //重載->運算符,獲取數據的地址
    pointer operator->()
    {
        return &(operator*());
    }
};

slist數據結構的定義

數據結構的定義如下,定義在slist.h的頭文件中:

//slist.h
#include "slist_iterator.h"
template<class T>
class slist{
    typedef T value_type;
    typedef value_type& reference;
    typedef const reference const_reference;
    typedef value_type* pointer;
    typedef const pointer const_pointer;

    typedef nodeStruct<T> node;
private:
    node* head;//設置一個頭結點
public:
    typedef iterator_<T, T&, T*> iterator;
    typedef iterator_<T, const T&, const T*> const_iterator;
    //構造函數初始化,將頭結點head的數據域data設置爲0,指針域next設置爲0
    //頭指針不存儲任何有用的數據,僅僅是爲了方便數據的運算操作而出現的
    slist(){
        head = new node();
        head->data = 0;
        head->next = 0;
    }
    //析構函數,使用完slist後,釋放每個節點的內存
    ~slist(){
        node* tmp = head->next;
        while (tmp != 0)
        {
            node* next = tmp->next;
            delete tmp;
            tmp = next;
        }
    }
    //向鏈表slist中插入節點,新節點一般插入到頭結點head的後面,所以節點的插入
    //的順序與它在鏈表中的順序是相反的
    void push_front(reference val)
    {
        //node* pn = (node*)(malloc(sizeof(node)));
        node* pn = new node();
        pn->data = val;
        pn->next = head->next;
        head->next = pn;
    }
    //將頭節點之後的第一個節點清除掉
    void pop_front()
    {
        if (head->next != 0)
        {
            node* pn = head->next;
            head->next = pn->next;
            delete pn;
        }
    }
    //獲取slist中節點的個數,不包含頭結點
    size_t size() const
    {
        size_t size=0;
        if (head->next == 0)
        {
            return 0;
        }
        node* tmp = head->next;
        while (tmp != 0)
        {
            size++;
            tmp = tmp->next;
        }
        return size;
    }
    //交換兩個slist
    void swap(slist& L)
    {
        node* tmp = head->next;
        L.head->next = tmp;
        head->next = L.head->next;
    }
    //判斷目前slist是否含有節點,不包含頭結點
    bool empty()const
    {
        return head->next == 0;
    }
    //從頭結點後的第一個節點開始,依次展示slist中存儲的所有數據
    void showList()const
    {
        node* tmp = head->next;
        while (tmp != 0)
        {
            cout << tmp->data << ' ';
            tmp = tmp->next;
        }
        cout << endl;
    }
    //獲取slist開始的迭代器
    iterator begin()
    {
        return iterator(head->next);
    }
    //獲取slist結束的迭代器
    iterator end()
    {
        return iterator(0);
    }
    //向slist中的某個位置之前插入節點,通過迭代器來完成
    iterator insert(iterator& iter, value_type val)
    {
        iterator beg = begin();
        while(beg != end())
        {
            iterator next = beg;
            ++next;
            if (next == iter)
            {
                node* tmp = new node();
                tmp->data = val;
                tmp->next = (beg.nnn)->next;
                (beg.nnn)->next = tmp;
                return iterator(tmp);返回當前插入位置的迭代器
            }
            beg = next;
        }
        return beg;//如果沒有找到要插入的位置,返回最後一個節點所表示的迭代器
    }
    //將slist中某個位置的節點刪除,通過迭代器來完成,返回所刪除節點指向的下一
    //個節點所表示的迭代器
    iterator erase(iterator& iter)
    {
        iterator beg = begin();
        while (beg != end())
        {
            iterator next = beg;
            ++next;
            if (next == iter)
            {
                (beg.nnn)->next = (iter.nnn)->next;
                delete iter.nnn;
                return ++beg;
            }
            beg = next;
        }
        return beg;
    }
};

至此,簡單的slist的已經完成,下面我們來做一小下測試:

//slistTest.h
#include "slist.h"
using namespace std;
int main(){
    slist<int> li;
    for (int i = 0; i < 10; i++)
        li.push_front(i);
    cout << "The initial sequence of integers is : ";
    li.showList();
    slist<int>::iterator beg = li.begin();
    beg += 4;//從首位置向後移四位
    slist<int>::iterator it=li.insert(beg,100);//插入100,返回插入節點所在位置的迭代器
    cout <<"The insert number is : "<< *it << endl;
    cout << "After insert the integer 100, the sequence of integers is :";
    li.showList();
    slist<int>::iterator cur = li.erase(beg);
    //cout << *cur << endl;
    cout << "After erase the iterator beg, the sequence of integers is :";
    li.showList();
    system("pause");
}

測試結果如下:
slist的測試結果
測試的結果是正確的!
通過實現slist的簡單實現,讓自己對迭代器有了深入的理解,其實說的明白一點迭代器就是一個被封裝的節點指針,通過給它賦值,自增等運算後可以指向任何位置的節點。廢話不多說了,《STL源碼解析》裏自己還有很多東西需要啃,加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章