单向链表-slist

原创 2016年08月29日 17:13:29

单向链表-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源码解析》里自己还有很多东西需要啃,加油!

相关文章推荐

STL源码剖析——单向链表slist

前言 在STL标准中提供de

zephyr学习笔记---单向链表slist

看了下zephyr所支持的开发板,有一个TI公司的,CC3200。低功耗wifi芯片,淘宝了一下,200出头,可以接受。当即买了一块,先弄TCP/IP再学6LowPan会好些。现在等开发板到货。 ...
  • abatei
  • abatei
  • 2017年03月27日 13:10
  • 326

单链表slist.c

  • 2012年03月15日 11:44
  • 3KB
  • 下载

STL源码笔记(16)—单链表slist

STL单链表slist简介

STL系列之八 slist单链表

微软的VS208所使用的PJ STL(注1)中的list是双链表,但在某些场合,一个轻量级的单链表会更加合适。单链表非常常见,这里就不去细说了,本文的slist(single linked list)...

单链表类:class Slist

//单链表 //内容:默认4个,增删6个,打印,查找 #pragma once #include #include using namespace std; typedef int DataTy...

java单向链表排序,倒置,合并

  • 2017年09月25日 11:18
  • 3KB
  • 下载

单向链表操作类模板实现代码

  • 2017年09月19日 15:57
  • 3KB
  • 下载

iOS开发之C语言单向链表的建立

1,为什么要用到链表 数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性。但数组也同样存在一些弊病。如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序...

单向链表的建立

  • 2015年07月11日 14:40
  • 4KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:单向链表-slist
举报原因:
原因补充:

(最多只允许输入30个字)