找南阳建立网站的公司,深圳标本制作,做网站的公司主要工作,沈阳市网站建设哪里的公司比较好欢迎来到我的Blog#xff0c;点击关注哦#x1f495; list的介绍和模拟实现 前言list介绍标准库容器 std::list 与 std::vector 的优缺点缺点 list的基本操作构造函数list iteratorlist capcacitylist modify list模拟实现存贮结构#xff08;双向带头循环#xff09;itera…欢迎来到我的Blog点击关注哦 list的介绍和模拟实现 前言list介绍标准库容器 std::list 与 std::vector 的优缺点缺点 list的基本操作构造函数list iteratorlist capcacitylist modify list模拟实现存贮结构双向带头循环iteratoriterator结构operator! operator operatoroperator-- list数据结构构造函数list的初始化节点初始化迭代器 list modifyinserterase头插、头删、尾插、尾删 list operator交换clear 源码 前言 string vector的是存储是基于物理空间上连续的而list是作为线性的链式结构是值得学习的。 list介绍
std::list是C标准模板库STL中的一个容器适配器它内部实现为双向链表结构。这种设计使得std::list能够在常数时间内进行任意位置的插入和删除操作这是其相对于其他序列容器如std::vector的显著优点。std::list不支持随机访问即无法直接通过索引来访问容器中的元素这通常需要从头部或尾部开始迭代到目标位置.
标准库容器 std::list 与 std::vector 的优缺点
std::list: 作为一个双向链表std::list 在插入和删除操作上具有优势因为这些操作只涉及到改变相邻节点的指针而不需要移动其他元素。此外std::list 不需要预分配额外的内存可以更好地处理动态内存分配减少内存碎片.std::vector: 作为一个动态数组std::vector 提供了高效的随机访问能力可以通过下标直接访问任意位置的元素其访问效率为 O(1). 此外std::vector 通常具有较高的空间利用率和缓存友好性因为其元素在内存中是连续存储的.
缺点
std::list: 由于非连续的内存存储std::list 在访问元素时效率较低因为可能需要从头开始遍历链表。此外每个节点都需要存储额外的指针信息这增加了内存开销.std::vector: 在 std::vector 的中间位置插入或删除元素可能会引起大量元素的移动以维持内存的连续性这会导致较差的性能。当 std::vector 的容量不足以容纳新增元素时还需要进行动态扩容这是一个成本较高的操作
vectorlist底层 结构动态顺序表一段连续空间带头结点的双向循环链表随 机 访 问支持随机访问访问某个元素效率O(1)不支持随机访问访问某个元素 效率O(N)插 入 删 除任意位置插入和删除效率低需要搬移元素时间复杂度为O(N)插入时有可能需要增容增容开辟新空 间拷贝元素释放旧空间导致效率更低任意位置插入和删除效率高不 需要搬移元素时间复杂度为 O(1)插 入 删 除底层为连续空间不容易造成内存碎片空间利用率 高缓存利用率高底层节点动态开辟小节点容易 造成内存碎片空间利用率低 缓存利用率低迭 代 器原生态指针对原生态指针(节点指针)进行封装迭 代 器 失 效在插入元素时要给所有的迭代器重新赋值因为插入 元素有可能会导致重新扩容致使原来迭代器失效删 除时当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效 删除元素时只会导致当前迭代 器失效其他迭代器不受影响使 用 场 景需要高效存储支持随机访问不关心插入删除效率大量插入和删除操作不关心随 机访问
list的基本操作
构造函数
【C】vector介绍以及模拟实现接口说明list (size_type n, const value_type val value_type())构造的list中包含n个值为val的元素list()构造空的listlist (const list x)拷贝构造函数list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list
list iterator
此处大家可暂时将迭代器理解成一个指针该指针指向list中的某个节点。
函数声明接口说明begin end返回第一个元素的迭代器返回最后一个元素下一个位置的迭代器rbegin rend返回第一个元素的reverse_iterator,即end位置返回最后一个元素下一个位置的 reverse_iterator,即begin位置
list capcacity
函数声明接口说明empty检测list是否为空是返回true否则返回falsesize返回list中有效节点的个数
list modify
函数声明接口说明push_front在list首元素前插入值为val的元素pop_front删除list中第一个元素push_back在list尾部插入值为val的元素pop_back删除list中最后一个元素insert在list position 位置中插入值为val的元素erase删除list position位置的元素swap交换两个list中的元素clear清空list中的有效元素
list模拟实现
存贮结构双向带头循环
定义一个类C语言结构体存储数据作为指向下一个上一个的节点
namespace MyList
{//LIst节点templateclass Tstruct _list_node{_list_nodeT* _next;_list_nodeT* _prev;T _val;_list_node(const T val T()): _next(nullptr), _prev(nullptr), _val(val){}};
}iterator
迭代器有两种实现方式具体应根据容器底层数据结构实现
原生态指针比如vector string将原生态指针进行封装因迭代器使用形式与指针完全相同因此在自定义的类中必须实现以下方法 1. 指针可以解引用迭代器的类中必须重载operator*() 2. 指针可以通过-访问其所指空间成员迭代器类中必须重载 oprator-() 3. 指针可以向后移动迭代器类中必须重载operator()与operator(int) 4. 迭代器需要进行是否相等的比较因此还需要重载operator()与operator!()
iterator结构
三个模板参数 第一个模板参数控制类型第二个模板参数控制返回值类型const 非const第三个模板参数控制返回的list类的类型const 非const Node* _node;需要定义一个指针指向list节点
templateclass T,class Ref,class ptrstruct _list_iterator{typedef _list_nodeT Node;typedef _list_iteratorT, Ref,ptr self;Node* _node;};operator! operator
//重载operator!
bool operator!(const self it)const
{return _node ! it._node;
}
//重载operator
bool operator(const self it)const
{return _node it._node;
}operator
//重载operator(前置)
self operator()
{_node _node-_next;return *this;
}
//重载operator(后置)
self operator(int)
{self tmp(*this);_node _node-_next;return tmp;
}operator--
//重载operator--(前置)
self operator--()
{_node _node-_prev;return *this;
}
//重载operator--(后置)
self operator--(int)
{self tmp(*this);_node _node-_prev;return tmp;
}operator* operator-
//重载operator*
Ref operator* ()
{return _node-_val;
}
//重载operator-
ptr operator-()
{return _node-_val;
}list数据结构
构造函数
list的初始化
双向带带头循环 #mermaid-svg-1LAJp6yJtxQBCAfN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .error-icon{fill:#552222;}#mermaid-svg-1LAJp6yJtxQBCAfN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1LAJp6yJtxQBCAfN .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-1LAJp6yJtxQBCAfN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1LAJp6yJtxQBCAfN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1LAJp6yJtxQBCAfN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1LAJp6yJtxQBCAfN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1LAJp6yJtxQBCAfN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1LAJp6yJtxQBCAfN .marker.cross{stroke:#333333;}#mermaid-svg-1LAJp6yJtxQBCAfN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1LAJp6yJtxQBCAfN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .cluster-label text{fill:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .cluster-label span{color:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .label text,#mermaid-svg-1LAJp6yJtxQBCAfN span{fill:#333;color:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .node rect,#mermaid-svg-1LAJp6yJtxQBCAfN .node circle,#mermaid-svg-1LAJp6yJtxQBCAfN .node ellipse,#mermaid-svg-1LAJp6yJtxQBCAfN .node polygon,#mermaid-svg-1LAJp6yJtxQBCAfN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1LAJp6yJtxQBCAfN .node .label{text-align:center;}#mermaid-svg-1LAJp6yJtxQBCAfN .node.clickable{cursor:pointer;}#mermaid-svg-1LAJp6yJtxQBCAfN .arrowheadPath{fill:#333333;}#mermaid-svg-1LAJp6yJtxQBCAfN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1LAJp6yJtxQBCAfN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1LAJp6yJtxQBCAfN .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-1LAJp6yJtxQBCAfN .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-1LAJp6yJtxQBCAfN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1LAJp6yJtxQBCAfN .cluster text{fill:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN .cluster span{color:#333;}#mermaid-svg-1LAJp6yJtxQBCAfN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1LAJp6yJtxQBCAfN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} _head //空list初始化
void empty_init()
{_head new Node;_head-_next _head;_head-_prev _head;_size 0;
}节点初始化
默认构造函数默认构造函数用迭代器初始化拷贝构造函数赋值运算符重载赋值运算符重载
//默认构造函数
list()
{empty_init();
}
//默认构造函数
list(int n, const T val T())
{empty_init();while (n--){push_back(val);}}
//用迭代器初始化
template class Iteratorlist(Iterator first, Iterator last)
{empty_init();while (first ! last){push_back(*first);first;}
}
//拷贝构造函数
list(const listT lt)
{empty_init();for (auto e : lt){push_back(e);}
}
//赋值运算符重载
listT operator(listT lt)
{swap(lt);return *this;
}
//赋值运算符重载
~list()
{clear();delete _head;
}迭代器
iterator begin()
{return _head-_next;
}
iterator end()
{return _head;
}
const_iterator begin()const
{return _head-_next;
}
const_iterator end()const
{return _head;
}list modify
insert
在pos位置插入节点同数据结构是一样的在这里面不过多赘述可以参考
//insert
iterator insert(iterator pos, const T x)
{Node* newcode new Node(x);Node* cur pos._node;Node* prev cur-_prev;prev-_next newcode;newcode-_prev prev;newcode-_next cur;cur-_prev newcode;_size;return pos;
}erase
删除迫使位置的节点同样可以参考
//erase
iterator erase(iterator pos)
{assert(pos._node ! _head);Node* cur pos._node;Node* prev cur-_prev;Node* next cur-_next;prev-_next next;next-_prev prev;delete cur;--_size;return next;
}头插、头删、尾插、尾删
可以复用insert ersae STL标准模板库也是进行复用
// 头插
void push_front(const T x)
{insert(begin(), x);
}
//头删
void pop_front()
{erase(begin());
}
//尾插
void push_back(const T x)
{insert(begin());
}
//尾删
void pop_back()
{erase(--end());
}list operator
交换
void swap(listT lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);}clear
析构函数也是利用了clear
//删除
void clear()
{iterator it begin();while (it ! end()){it erase(it);it;}}源码
#pragma once
#include iostream
#include assert.hnamespace MyList
{//节点templateclass Tstruct _list_node{_list_nodeT* _next;_list_nodeT* _prev;T _val;_list_node(const T val T()): _next(nullptr), _prev(nullptr), _val(val){}};//迭代器templateclass T,class Ref,class ptrstruct _list_iterator{typedef _list_nodeT Node;typedef _list_iteratorT, Ref,ptr self;Node* _node;_list_iterator (Node* node):_node(node){}//重载operator*Ref operator* (){return _node-_val;}//重载operator-ptr operator-(){return _node-_val;}//重载operator(前置)self operator(){_node _node-_next;return *this;}//重载operator(后置)self operator(int){self tmp(*this);_node _node-_next;return tmp;}//重载operator--(前置)self operator--(){_node _node-_prev;return *this;}//重载operator--(后置)self operator--(int){self tmp(*this);_node _node-_prev;return tmp;}//重载operator!bool operator!(const self it)const {return _node ! it._node;}//重载operatorbool operator(const self it)const{return _node it._node;}};//listtemplateclass Tclass list{typedef _list_nodeT Node;public:typedef _list_iteratorT, T,T* iterator;typedef _list_iteratorT, const T,const T* const_iterator;//空list初始化void empty_init(){_head new Node;_head-_next _head;_head-_prev _head;_size 0;}//用n个val初始化list(int n, const T val T()){empty_init();while (n--){push_back(val);}}//用迭代器初始化template class Iteratorlist(Iterator first, Iterator last){empty_init();while (first ! last){push_back(*first);first;}}//默认构造函数list(){empty_init();}//拷贝构造函数list(const listT lt){empty_init();for (auto e : lt){push_back(e);}}//赋值运算符重载listT operator(listT lt){swap(lt);return *this;}//析构函数~list(){clear();delete _head;}//删除void clear(){iterator it begin();while (it ! end()){it erase(it);it;}}//迭代器iterator begin(){return _head-_next;}iterator end(){return _head;}const_iterator begin()const{return _head-_next;}const_iterator end()const{return _head;}//void push_back(const T x)//{// Node* newcode new Node(x);// Node* tail _head-_prev;// tail-_next newcode;// newcode-_next _head;// newcode-_prev tail;// _head-_prev newcode;// _size;//}// 头插void push_front(const T x){insert(begin(), x);}//头删void pop_front(){erase(begin());}//尾插void push_back(const T x){insert(begin());}//尾删void pop_back(){erase(--end());}//insertiterator insert(iterator pos, const T x){assert(pos._node ! _head);Node* newcode new Node(x);Node* cur pos._node;Node* prev cur-_prev;prev-_next newcode;newcode-_prev prev;newcode-_next cur;cur-_prev newcode;_size;return pos;}//eraseiterator erase(iterator pos){assert(pos._node ! _head);Node* cur pos._node;Node* prev cur-_prev;Node* next cur-_next;prev-_next next;next-_prev prev;delete cur;--_size;return next;}//大小size_t size()const{return _size;}//交换void swap(listT lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}private:Node* _head;size_t _size;};}