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

单向链表和双向链表的原理及其相关实现

链表是线性表的一种,所谓的线性表包含顺序线性表和链表,顺序线性表是用数组实现的,在内存中有顺序排列,通过改变数组大小实现。而链表不是用顺序实现的,用指针实现,在内存中不连续。而链表又包括单向链表、双向...
  • Jasmine_shine
  • Jasmine_shine
  • 2015年03月03日 09:21
  • 8119

单向链表的Java实现,以及相关函数。

如上图所示就是单向链表的示意图: 下面就是Java实现单向链表的基本过程与源码,可以跑起来的。 1.创建一个节点类 package com.wpl.snglelink; public clas...
  • daguairen
  • daguairen
  • 2016年10月05日 13:34
  • 713

单向链表--java实现

我们都知道,java中自带了许多的数据结构。这些数据结构被封装的很好,使得我们用的很方便,但是我们却不知道这些数据结构具体是怎么实现的。 于是,自己尝试着实现了一个链表。单向链表示意图: 单向链表...
  • u014039577
  • u014039577
  • 2015年12月22日 17:10
  • 866

Linux C 学习 单向链表

最近从Linux C数据结构和算法学起,下面是一个单向链表的写法,代码如下: #include #include int n=0; typedef struct code {  int dat...
  • zqixiao_09
  • zqixiao_09
  • 2015年11月17日 21:01
  • 1387

单向链表的C语言实现与基本操作

本文的主要内容目录: 一、单向链表的C语言实现 二、单向链表的基本操作 一、单向链表的C语言实现 链表作为一种基本的数据结构在程序开发过程当中经常会使用到。对C语言来说链表的实现主要依靠结构体和指...
  • TECH_PRO
  • TECH_PRO
  • 2017年04月17日 05:59
  • 2046

c语言:单向循环链表的实现

// 单循环链表的实现.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include #include #define LEN sizeo...
  • qq_28598203
  • qq_28598203
  • 2016年03月26日 02:05
  • 993

单向链表的简单使用

一、单向链表的概念     单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。链表是使用指针进行构造的列表,并且是由一个个结点组装起来的,因此又称为结点列表。...
  • silent123go
  • silent123go
  • 2016年09月28日 20:52
  • 1347

《链表》——单向链表和双向链表(Java)

完整的代码地址为:github  点击查看 单链表 单链表包括数据域和指向下一个节点的指针域,其结构如上图所示 首先定义一个数据类: class DATA{ //定义链表的一个...
  • Gamer_gyt
  • Gamer_gyt
  • 2016年05月20日 20:03
  • 1825

单向链表之C++实现

单向链表是常用的数据结构,之前只是看过,没有自己动手实现过,现在来
  • KangRoger
  • KangRoger
  • 2014年07月01日 21:20
  • 8152

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

看了下zephyr所支持的开发板,有一个TI公司的,CC3200。低功耗wifi芯片,淘宝了一下,200出头,可以接受。当即买了一块,先弄TCP/IP再学6LowPan会好些。现在等开发板到货。 ...
  • abatei
  • abatei
  • 2017年03月27日 13:10
  • 423
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:单向链表-slist
举报原因:
原因补充:

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