【STL源码剖析读书笔记】【第4章】序列式容器之list和slist

2023-10-18 05:48

本文主要是介绍【STL源码剖析读书笔记】【第4章】序列式容器之list和slist,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、list

1、list概述

list是双向链表,对于任何位置的元素插入或元素移除,list永远是常数时间。

2、list的节点

list本身和list节点是不同的数据结构,需要分开设计。STL list的节点结构:

template <class T>
struct __list_node {typedef void* void_pointer;void_pointer next;void_pointer prev;T data;
};
3、 list 的迭代器

STL list是一个双向链表,迭代器必须具备前移、后移的能力,list提供的是Bidirectional Iteratorslist的插入操作和接合操作都不会导致原来的list迭代器失效。


4、list的数据结构

STL list是一个环状双向链表,只需一个指针就可以表现整个链表。

template<class T,class Alloc = alloc> //缺省使用alloc为配置器:w
class list{
protected :typedef	__list_node<T> list_node ;
public  :typedef	list_node* link_type ;
protected :link_type node ; //只要一个指针,便可以表示整个环状双向链表
};
如果让指针 node 指向刻意置于尾端的一个空白节点, node 便能符合 STL 对于“前闭后开”区间的要求,成为 last 迭代器。


5、insert()函数

insert()是一个重载函数,最简单的一种如下:

iterator insert(iterator position, const T& x){//在迭代器position所指位置插入一个节点,内容为xlink_type tmp = create_node(x);tmp->next = position.node;tmp->prev = position.node->node;(link_type(position.node->prev))->next = tmp;return tmp;
}

6、push_back()函数

将新元素插入于list尾端,内部调用insert()函数

void push_back(const T& x){
insert(end(),x);
}
7、 push_front() 函数

将新元素插入于list头端,内部调用insert()函数

void push_front(const T&x){
insert(begin(),x);
}
8、 erase() 函数

iterator erase(iterator position){
link_type next_node=link_type(position.node->next);
link_type prev_node=link_type(position.node->prev_nodext);
prev_node->next=next_node;
next_node->prev=prev_node;
destroy_node(position.node);
return iterator(next_node);
}

9、pop_front()函数

移除头结点,内部调用erase()函数

void pop_front(){
erase(begin());
}
10、 pop_back() 函数

移除尾结点,内部调用erase()函数

void pop_back(){
iterator i=end();
erase(--i);
}
11、 transfer() 函数

将某连续范围的元素迁移到某个特定位置之前。

void transfer(iterator position, iterator first, iterator last) {if (position != last) {(*(link_type((*last.node).prev))).next = position.node; //(1)(*(link_type((*first.node).prev))).next = last.node;    //(2)(*(link_type((*position.node).prev))).next = first.node;//(3)link_type tmp = link_type((*position.node).prev);       //(4)(*position.node).prev = (*last.node).prev;              //(5)(*last.node).prev = (*first.node).prev;                 //(6)(*first.node).prev = tmp;                               //(7)}}

二、slist

1slist概述

SGI STL另提供一个单向链表slistslistlist的主要差别在于,前者的迭代器属于单向的Forward Iterator,后者的迭代器属于双向的BidirectionalIterator

根据STL的习惯,插入操作会将新元素插入于指定位置之前。作为单向链表,slist没有任何方便的方法可以回头定出前一个位置,因此它必须从头找起。

2、slist的节点

3、slist的迭代器


4、slist的数据结构

template<class T, class Alloc = alloc>
class slist
{
public :typedef	T	value_type ;typedef	value_type*	pointer ; typedef	const	value_type*	const_pointer ;typedef	value_type&	reference ;typedef	const value_type& const_reference ;typedef	size_t	size_type ;typedef	ptrdiff_t	difference_type ;typedef	__slist_iterator<T,T&,T*>	iterator ;typedef	__slist_iterator<T,const T&,const T*> const_iterator ;private :typedef	__slist_node<T>	list_node ;typedef	__slist_node_base	list_node_base ;typedef	__slist_iterator_base	iterator_base ;typedef simple_alloc<list_node,Alloc> list_node_allocator ;static	list_node* create_node(const value_type& x){list_node* node = list_node_allocator:;allocate() ; //配置空间__STL_TRY{construct(&node->data,x) ;node->next = 0 ;}__STL_UNWIND(list_node_allocator:;deallocate(node)) ;return node ;}static void destroy_node(list_node* node){destroy(&node->data) ; //将元素析构	list_node_allocator::deallocate(node) ; //释放空间}private :list_node_base head  ; //头部。注意,它不是指针,是实物public:slist() {head.next = 0 ;} ~slist(){clear() ;}public :iterator begin() {return iterator((list_node*)head.next) ;}iterator end() {return iteator(0) ;}iterator size() {const __slist_size(head.next) ;}bool empty() const {return head.next == 0 ;} //两个slist互换:只要将head交换互指即可void swap(slist &L){list_node_base* tmp = head.next;head.next = L.head.next ;L.head.next = tmp ;}public ://取头部元素reference front() {return ((list_node*)head.next)->data ;}//从头部插入元素(新元素成为slist的第一个元素)void push_front(const value_type& x){__slist_make_link(&head,create_node(x)) ;}//注意,没有push_back()//从头部取走元素(删除之)。修改headvoid pop_front(){list_node* node = (list_node*)head.next ;head.next = node->next ;destroy_node(node);}.....
}  ;
5、 slist 的元素操作





这篇关于【STL源码剖析读书笔记】【第4章】序列式容器之list和slist的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/230578

相关文章

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

python3如何找到字典的下标index、获取list中指定元素的位置索引

《python3如何找到字典的下标index、获取list中指定元素的位置索引》:本文主要介绍python3如何找到字典的下标index、获取list中指定元素的位置索引问题,具有很好的参考价值,... 目录enumerate()找到字典的下标 index获取list中指定元素的位置索引总结enumerat

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Python中合并列表(list)的六种方法小结

《Python中合并列表(list)的六种方法小结》本文主要介绍了Python中合并列表(list)的六种方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录一、直接用 + 合并列表二、用 extend() js方法三、用 zip() 函数交叉合并四、用

利用Python实现时间序列动量策略

《利用Python实现时间序列动量策略》时间序列动量策略作为量化交易领域中最为持久且被深入研究的策略类型之一,其核心理念相对简明:对于显示上升趋势的资产建立多头头寸,对于呈现下降趋势的资产建立空头头寸... 目录引言传统策略面临的风险管理挑战波动率调整机制:实现风险标准化策略实施的技术细节波动率调整的战略价

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、