单向链表-slist

单向链表-slist

博主所分享的这个单向链表slist,是依据侯捷老师的《STL源码解析》中slist一节的slist,因为博主在跑书上slist上的例子时,发现#include <slist> <script type="math/tex" id="MathJax-Element-51"> </script>报错,编译器并没有提供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源码解析》里自己还有很多东西需要啃,加油!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值