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

本文介绍了STL中的单链表slist,它是一种单向链表,与list的区别在于迭代器类型。slist的迭代器是Forward Iterator,不支持双向读写。尽管其功能相对有限,但在空间占用和某些操作速度上有优势。slist的源码分析包括节点设计,使用继承实现链表节点,包含数据和指向下一个节点的指针。迭代器设计同样采用继承,且slist仅提供push_front(),不提供push_back(),以保持插入效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STL单链表slist简介

概述

slist(Single linked list)顾名思义,是一个单向链表,这个容器并不在标准规格之内,在我几年的代码学习生涯中也是第一次听说,既然侯老师的书中提到了,那也还是学习一蛤。

slist与list的主要差别是,前者的迭代器属于单向的Forward Iterator(可读写),后者的迭代器属于双向的Bidirectional Iterator(可以双向读写)。看起来slist的功能应该会不如list,但由于其单向链表的实现,其消耗的空间更小,某些操作更快。

回忆数据结构中在单链表的某个位置插入元素的过程,slist的底层实现就是单链表,因此会遇到我们曾经遇到过的麻烦:在某个位置插入时,必须要用一个指针从头到尾找到待插入位置的前一个位置。这便是在slist的一个大的缺点之一,因此,书中提到,在非起点位置使用insert或erase的算法是不智之举。


slist源码实现

在SGI STL源码中,slist的实现位于stl_slist.h

节点设计

容器的核心就是其底层存储于迭代器设计了,对于节点设计,使用了继承的关系,实际上简单的来说就是单链表的节点:指向下一个节点的指针和数据

这里写图片描述

代码实现如下:

//stl_slist.h
//单向链表的节点结构
struct _Slist_node_base
{
  _Slist_node_base* _M_next;
};
//使用继承来实现单链表的节点结构:指针+数据 
template <class _Tp>
struct _Slist_node : public _Slist_node_base
{
  _Tp _M_data;
};

基于单链表的特性和节点的结构,源码中提供了不少内部全局函数,这些函数不对外开放的,仅仅在某些对外使用的接口实现中直接调用,例如:

//全局函数:单链表节点数,其实就是简单的遍历计数
inline size_t __slist_size(_Slist_node_base* __node)
{
  size_t __result = 0;
  for ( ; __node != 0; __node = __node->_M_next)
    ++__result;
  return __result;
}
//全局函数:已知某一节点,插入新节点于其后
//返回插入节点之后的指针。
inline _Slist_node_base*
__slist_make_link(_Slist_node_base* __prev_node,
                  _Slist_node_base* __new_node)
{
  __new_node->_M_next = __prev_node->_M_next;
  __prev_node->_M_next = __new_node;
  return __new_node;
}

迭代器设计

如上图所示,迭代器同样是使用了继承的方式:

//单向链表的迭代器基本结构
struct _Slist_iterator_base
{
  typedef size_t               size_type;
  typedef ptrdiff_t            difference_type;
  typedef forward_it
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值